Add remaining project files
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
using DeluxeBackend.Models;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Numerics;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace DeluxeBackend.Services
|
||||
{
|
||||
|
||||
public interface ICdnService
|
||||
{
|
||||
Task<string?> UploadFile(Stream fileStream, string filePath);
|
||||
Task<string?> UploadFile(Stream fileStream, string filePath, string fileName);
|
||||
Task<(string? Url, string? Proof)> UploadFile(Stream fileStream, string filePath, Account account);
|
||||
}
|
||||
|
||||
public class CdnService(HttpClient httpClient) : ICdnService
|
||||
{
|
||||
public static readonly string Url = "http://127.0.0.1:9823/";
|
||||
|
||||
private static readonly string apiUrl = "http://127.0.0.1:9823/api/internal/v1/upload";
|
||||
private readonly string apiKey = "KittyRec_6767_1b9b24fe-eb5a-486b-af29-dba01b8de861";
|
||||
private static readonly string proofSecret = "SUPER_SECRET_OWNERSHIP_SIGNING_KEY_12345";
|
||||
|
||||
|
||||
public async Task<string?> UploadFile(Stream fileStream, string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var request = new HttpRequestMessage(HttpMethod.Post, apiUrl);
|
||||
|
||||
request.Headers.Add("X-API-KEY", apiKey);
|
||||
|
||||
var content = new MultipartFormDataContent();
|
||||
|
||||
var fileContent = new StreamContent(fileStream);
|
||||
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
|
||||
content.Add(fileContent, "file", "data.bin");
|
||||
|
||||
content.Add(new StringContent(filePath), "type");
|
||||
|
||||
request.Content = content;
|
||||
|
||||
var response = await httpClient.SendAsync(request);
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Upload failed: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal static string GenerateOwnershipProof(Account account, string fileName)
|
||||
{
|
||||
var payload = $"{Environment.MachineName}:{account.Id}:{account.CreatedAt.Ticks}:{fileName}";
|
||||
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(proofSecret));
|
||||
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(payload));
|
||||
return Convert.ToBase64String(hash);
|
||||
}
|
||||
public async Task<string?> UploadFile(Stream fileStream, string filePath, string fileName)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var request = new HttpRequestMessage(HttpMethod.Post, apiUrl);
|
||||
|
||||
request.Headers.Add("X-API-KEY", apiKey);
|
||||
|
||||
var content = new MultipartFormDataContent();
|
||||
|
||||
var fileContent = new StreamContent(fileStream);
|
||||
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
|
||||
content.Add(fileContent, "file", "data.bin");
|
||||
|
||||
content.Add(new StringContent(filePath), "type");
|
||||
content.Add(new StringContent(fileName), "filename");
|
||||
|
||||
request.Content = content;
|
||||
|
||||
var response = await httpClient.SendAsync(request);
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Upload failed: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<(string? Url, string? Proof)> UploadFile(Stream fileStream, string filePath, Account account)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var request = new HttpRequestMessage(HttpMethod.Post, apiUrl);
|
||||
|
||||
request.Headers.Add("X-API-KEY", apiKey);
|
||||
|
||||
var content = new MultipartFormDataContent();
|
||||
|
||||
var fileContent = new StreamContent(fileStream);
|
||||
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
|
||||
content.Add(fileContent, "file", "data.bin");
|
||||
|
||||
content.Add(new StringContent(filePath), "type");
|
||||
|
||||
request.Content = content;
|
||||
|
||||
var response = await httpClient.SendAsync(request);
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
string fileName = await response.Content.ReadAsStringAsync();
|
||||
string proof = GenerateOwnershipProof(account, fileName);
|
||||
|
||||
return (fileName, proof);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return (null, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Upload failed: {ex.Message}");
|
||||
return (null, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
using DeluxeBackend;
|
||||
using DeluxeBackend.Models;
|
||||
using DeluxeBackend.Services;
|
||||
using Discord;
|
||||
using Discord.Interactions;
|
||||
using Discord.WebSocket;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using static AGRoomRuntimeConfig;
|
||||
using static DeluxeBackend.Controllers.Api.PlayerReportingController;
|
||||
|
||||
public class DiscordBotService : BackgroundService
|
||||
{
|
||||
private readonly DiscordSocketClient _client;
|
||||
private readonly InteractionService _interactions;
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly ILogger<DiscordBotService> _logger;
|
||||
private readonly IConfiguration _config;
|
||||
private readonly ILiteDbService _db;
|
||||
private readonly INotificationService _ws;
|
||||
|
||||
public readonly ulong guild = 1495287391324340297;
|
||||
|
||||
public DiscordBotService(
|
||||
ILogger<DiscordBotService> logger,
|
||||
IConfiguration config,
|
||||
DiscordSocketClient client,
|
||||
InteractionService interactions,
|
||||
IServiceProvider services,
|
||||
ILiteDbService dv,
|
||||
INotificationService notification
|
||||
)
|
||||
{
|
||||
_logger = logger;
|
||||
_config = config;
|
||||
_client = client;
|
||||
_interactions = interactions;
|
||||
_services = services;
|
||||
_db = dv;
|
||||
_ws = notification;
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
_client.Log += LogAsync;
|
||||
_interactions.Log += LogAsync;
|
||||
|
||||
_client.InteractionCreated += async interaction =>
|
||||
{
|
||||
var ctx = new SocketInteractionContext(_client, interaction);
|
||||
await _interactions.ExecuteCommandAsync(ctx, _services);
|
||||
|
||||
};
|
||||
_client.GuildMemberUpdated += HandleMemberUpdated;
|
||||
|
||||
_client.Ready += async () =>
|
||||
{
|
||||
await _interactions.AddModulesAsync(Assembly.GetEntryAssembly(), _services);
|
||||
|
||||
await _interactions.RegisterCommandsToGuildAsync(guild);
|
||||
|
||||
_logger.LogInformation("Discord Slash Commands registered!");
|
||||
};
|
||||
|
||||
var token = _config["DiscordToken"];
|
||||
await _client.LoginAsync(TokenType.Bot, token);
|
||||
await _client.StartAsync();
|
||||
|
||||
await Task.Delay(-1, stoppingToken);
|
||||
}
|
||||
|
||||
private async Task HandleMemberUpdated(Cacheable<SocketGuildUser, ulong> before, SocketGuildUser user)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Account account = _db.Accounts.FindOne(x => x.DiscordId == user.Id);
|
||||
if (account == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
await _ws.SendToPlayer(account.Id, PushNotification.RefreshLogin, new Dictionary<string, object>());
|
||||
}
|
||||
|
||||
private Task LogAsync(LogMessage msg)
|
||||
{
|
||||
_logger.LogInformation(msg.ToString());
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task<bool> HasUserBoostedGuild(ulong userId)
|
||||
{
|
||||
var targetGuild = _client.GetGuild(guild);
|
||||
if (targetGuild == null)
|
||||
{
|
||||
_logger.LogWarning($"Guild {guild} not found or not cached.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var user = targetGuild.GetUser(userId) ?? targetGuild.GetUser(userId) as SocketGuildUser;
|
||||
|
||||
if (user == null) return false;
|
||||
|
||||
if (user.Roles.Any(r => r.Id == 1503514258913103914))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return user.PremiumSince.HasValue;
|
||||
}
|
||||
|
||||
|
||||
public static readonly Dictionary<ulong, string> RoleMaping = new()
|
||||
{
|
||||
[1495587327593021490] = "moderator",
|
||||
[1495580320525844581] = "developer",
|
||||
[1495909230643908729] = "developer",
|
||||
[1495580027453046804] = "developer",
|
||||
[1501711512996282369] = "developer",
|
||||
[1495580006712213674] = "developer",
|
||||
[1503659138507341834] = "screenshare",
|
||||
[1495635212531400875] = "booster",
|
||||
[1508830399625695353] = "betastudio"
|
||||
};
|
||||
public async Task<List<string>> UserRoles(ulong userId)
|
||||
{
|
||||
var targetGuild = _client.GetGuild(guild);
|
||||
if (targetGuild == null)
|
||||
{
|
||||
_logger.LogWarning($"Guild {guild} not found or not cached.");
|
||||
return [];
|
||||
}
|
||||
|
||||
var user = targetGuild.GetUser(userId);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
/*try
|
||||
{
|
||||
user = await _client.Rest.GetGuildUserAsync(guild, userId);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return [];
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
if (user == null) return [];
|
||||
|
||||
return [.. user.Roles.Where(r => RoleMaping.ContainsKey(r.Id)).Select(r => RoleMaping[r.Id]).Distinct()];
|
||||
}
|
||||
|
||||
public async Task<bool> HasRole(ulong userId, string role)
|
||||
{
|
||||
var roles = await UserRoles(userId);
|
||||
return roles.Any(r => r.Equals(role, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
public async Task SendSelfReport(Account account, PGGOOHJPFPC hileType, string message)
|
||||
{
|
||||
var channel = _client.GetChannel(1506679765011267818) as IMessageChannel;
|
||||
if (channel != null)
|
||||
{
|
||||
Embed embed = new EmbedBuilder().WithTitle($"@{account.Username} ({account.Id}) sent a hile report").WithDescription($"{hileType}: {message}").WithAuthor(account.Username, $"{ServerConfig.ImgApiUrl}{account.ImageName ?? "DefaultProfileImage"}?height=192&cropSquare=true").Build();
|
||||
await channel.SendMessageAsync(null, false, embed, null, AllowedMentions.None);
|
||||
}
|
||||
}
|
||||
public async Task SendSavedImg(Account account, SavedImage image)
|
||||
{
|
||||
var channel = _client.GetChannel(1507036679838634006) as IMessageChannel;
|
||||
if (channel != null)
|
||||
{
|
||||
Embed embed = new EmbedBuilder().
|
||||
WithAuthor(account.Username, $"{ServerConfig.ImgApiUrl}{account.ImageName ?? "DefaultProfileImage"}?height=192&cropSquare=true")
|
||||
.WithTitle($"@{account.Username} ({account.Id}) uploaded a image")
|
||||
.WithDescription($"RoomId: {image.RoomId}")
|
||||
.WithImageUrl($"{ServerConfig.ImgApiUrl}{image.ImageName}")
|
||||
.WithTimestamp(image.CreatedAt)
|
||||
.Build();
|
||||
var components = new ComponentBuilder()
|
||||
.WithButton("Open Raw", null, ButtonStyle.Link, null, $"https://dev-cdn-kr.oldrecroom.com/img/{image.ImageName}")
|
||||
.Build();
|
||||
await channel.SendMessageAsync(null, false, embed, null, AllowedMentions.None, null, components);
|
||||
}
|
||||
var channel2 = _client.GetChannel(1509542402744909955) as IMessageChannel;
|
||||
if (channel2 != null)
|
||||
{
|
||||
if (image.Accessibility == Enums.SavedImageAccessibility.Public && image.SavedImageType == Enums.SavedImageType.ShareCamera)
|
||||
{
|
||||
Embed embed2 = new EmbedBuilder().
|
||||
WithAuthor(account.Username, $"{ServerConfig.ImgApiUrl}{account.ImageName ?? "DefaultProfileImage"}?height=192&cropSquare=true")
|
||||
.WithTitle($"Image uploaded")
|
||||
.WithImageUrl($"{ServerConfig.ImgApiUrl}{image.ImageName}")
|
||||
.WithTimestamp(image.CreatedAt)
|
||||
.Build();
|
||||
await channel2.SendMessageAsync(null, false, embed2, null, AllowedMentions.None, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
using DeluxeBackend.Models;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Numerics;
|
||||
using System.Security.Claims;
|
||||
using static DeluxeBackend.Enums;
|
||||
|
||||
namespace DeluxeBackend.Services
|
||||
{
|
||||
|
||||
public class LoginWithInfoResult
|
||||
{
|
||||
public required Account Account { get; set; }
|
||||
public PlatformType Platform { get; set; }
|
||||
public required string PlatformId { get; set; }
|
||||
public DeviceClassType DeviceClass { get; set; }
|
||||
public required string Locale { get; set; }
|
||||
public required string AppVersion { get; set; }
|
||||
}
|
||||
|
||||
public interface IJwtService
|
||||
{
|
||||
Task<string> GenAccessToken(Account account, List<string> roles, Dictionary<string, object>? customeClaims = null);
|
||||
Task<string> GenRefreshToken(Account acc);
|
||||
Task<Account?> GetLogin(ClaimsPrincipal? User);
|
||||
Task<LoginWithInfoResult?> GetLoginWithInfo(ClaimsPrincipal? User);
|
||||
}
|
||||
|
||||
public class JwtService : IJwtService
|
||||
{
|
||||
private readonly ILiteDbService db;
|
||||
private readonly IConfiguration configuration;
|
||||
private readonly DiscordBotService discord;
|
||||
|
||||
public JwtService(ILiteDbService _db, IConfiguration _configuration, DiscordBotService _discord)
|
||||
{
|
||||
db = _db;
|
||||
configuration = _configuration;
|
||||
discord = _discord;
|
||||
}
|
||||
|
||||
public async Task<string> GenAccessToken(Account account, List<string> roles, Dictionary<string, object>? customeClaims = null)
|
||||
{
|
||||
var issuer = configuration["JwtConfig:Issuer"];
|
||||
var key = new SymmetricSecurityKey(Convert.FromBase64String(configuration["JwtConfig:Key"]));
|
||||
var exp = DateTime.UtcNow.AddHours(1).AddMinutes(10);
|
||||
|
||||
roles.AddRange(account.Roles);
|
||||
if (account.DiscordId.HasValue)
|
||||
{
|
||||
roles.AddRange(await discord.UserRoles(account.DiscordId.Value));
|
||||
}
|
||||
if (account.IsJunior == null || account.IsJunior == true)
|
||||
{
|
||||
roles.Add("junior");
|
||||
}
|
||||
roles = roles.Distinct().ToList();
|
||||
|
||||
var claimsDictionary = new Dictionary<string, object>
|
||||
{
|
||||
["role"] = roles
|
||||
};
|
||||
|
||||
if (customeClaims != null)
|
||||
{
|
||||
foreach (var claim in customeClaims)
|
||||
{
|
||||
claimsDictionary[claim.Key] = claim.Value;
|
||||
}
|
||||
}
|
||||
|
||||
var tokenDect = new SecurityTokenDescriptor
|
||||
{
|
||||
Subject = new ClaimsIdentity(
|
||||
[
|
||||
new Claim("sub", account.Id.ToString())
|
||||
]),
|
||||
IssuedAt = DateTime.UtcNow,
|
||||
Claims = claimsDictionary,
|
||||
Expires = exp,
|
||||
Issuer = issuer,
|
||||
SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature),
|
||||
};
|
||||
|
||||
var tokenHandler = new JwtSecurityTokenHandler();
|
||||
var token = tokenHandler.WriteToken(tokenHandler.CreateToken(tokenDect));
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
public Task<string> GenRefreshToken(Account acc)
|
||||
{
|
||||
RefreshToken refreshToken = new()
|
||||
{
|
||||
Token = Convert.ToBase64String(Guid.NewGuid().ToByteArray()),
|
||||
Expires = DateTime.UtcNow.AddDays(2),
|
||||
Account = acc
|
||||
};
|
||||
db.RefreshTokens.Insert(refreshToken);
|
||||
return Task.FromResult(refreshToken.Token);
|
||||
}
|
||||
|
||||
public Task<Account?> GetLogin(ClaimsPrincipal? User = null)
|
||||
{
|
||||
Console.WriteLine(User);
|
||||
if (User == null)
|
||||
return Task.FromResult<Account?>(null);
|
||||
|
||||
string? rawPlayerId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value
|
||||
?? User.FindFirst("sub")?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(rawPlayerId))
|
||||
return Task.FromResult<Account?>(null);
|
||||
|
||||
if (!long.TryParse(rawPlayerId, out long playerId))
|
||||
return Task.FromResult<Account?>(null);
|
||||
|
||||
Account? player = db.Accounts.FindById(playerId);
|
||||
|
||||
return Task.FromResult<Account?>(player);
|
||||
}
|
||||
public Task<LoginWithInfoResult?> GetLoginWithInfo(ClaimsPrincipal? User = null)
|
||||
{
|
||||
if (User == null)
|
||||
return Task.FromResult<LoginWithInfoResult?>(null);
|
||||
|
||||
string? rawPlayerId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value
|
||||
?? User.FindFirst("sub")?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(rawPlayerId) || !long.TryParse(rawPlayerId, out long playerId))
|
||||
return Task.FromResult<LoginWithInfoResult?>(null);
|
||||
|
||||
Account? player = db.Accounts.FindById(playerId);
|
||||
if (player == null)
|
||||
return Task.FromResult<LoginWithInfoResult?>(null);
|
||||
|
||||
var result = new LoginWithInfoResult
|
||||
{
|
||||
Account = player,
|
||||
PlatformId = User.FindFirst("db.platform.id")?.Value,
|
||||
Locale = User.FindFirst("db.locale")?.Value,
|
||||
AppVersion= User.FindFirst("db.appver")?.Value,
|
||||
};
|
||||
|
||||
string? rawPlatform = User.FindFirst("db.platform")?.Value;
|
||||
if (Enum.TryParse<PlatformType>(rawPlatform, out var platform))
|
||||
{
|
||||
result.Platform = platform;
|
||||
}
|
||||
|
||||
string? rawDeviceClass = User.FindFirst("db.deviceclass")?.Value;
|
||||
if (Enum.TryParse<DeviceClassType>(rawDeviceClass, out var deviceClass))
|
||||
{
|
||||
result.DeviceClass = deviceClass;
|
||||
}
|
||||
|
||||
return Task.FromResult<LoginWithInfoResult?>(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using DeluxeBackend.Models;
|
||||
using LiteDB;
|
||||
using System.Numerics;
|
||||
|
||||
namespace DeluxeBackend.Services
|
||||
{
|
||||
public interface ILiteDbService
|
||||
{
|
||||
ILiteCollection<Account> Accounts { get; }
|
||||
ILiteCollection<Cachedlogin> Cachedlogins { get; }
|
||||
ILiteCollection<RefreshToken> RefreshTokens { get; }
|
||||
ILiteCollection<Room> Rooms { get; }
|
||||
ILiteCollection<SubRoom> SubRooms { get; }
|
||||
ILiteCollection<AccountPresence> Presences { get; }
|
||||
ILiteCollection<RoomInstance> RoomInstances { get; }
|
||||
ILiteCollection<AccountSetting> Settings { get; }
|
||||
ILiteCollection<AccountAvatar> Avatar { get; }
|
||||
ILiteCollection<SubRoomSave> SubRoomSave { get; }
|
||||
ILiteCollection<UnityAssets> UnityAssets { get; }
|
||||
ILiteCollection<ActionLink> ActionLinks { get; }
|
||||
ILiteCollection<Relationship> Relationships { get; }
|
||||
ILiteCollection<Message> Messages { get; }
|
||||
ILiteCollection<SavedImage> SavedImages { get; }
|
||||
ILiteCollection<AvatarSaved> AvatarSaveds { get; }
|
||||
ILiteCollection<PlayerEvent> PlayerEvents { get; }
|
||||
ILiteCollection<PlayerInvite> PlayerInvites { get; }
|
||||
ILiteCollection<CustomAvatarItem> CustomAvatarItems { get; }
|
||||
ILiteCollection<Invention> Inventions { get; }
|
||||
|
||||
}
|
||||
public class LiteDbService : ILiteDbService
|
||||
{
|
||||
private readonly LiteDatabase _db;
|
||||
|
||||
public LiteDbService()
|
||||
{
|
||||
_db = new LiteDatabase(Path.Combine(Path.Combine(Directory.GetCurrentDirectory(), "..", "Deluxe.db")));
|
||||
}
|
||||
|
||||
public ILiteCollection<Account> Accounts => _db.GetCollection<Account>("accounts");
|
||||
public ILiteCollection<Cachedlogin> Cachedlogins => _db.GetCollection<Cachedlogin>("cachedlogins");
|
||||
public ILiteCollection<RefreshToken> RefreshTokens => _db.GetCollection<RefreshToken>("refreshtokens");
|
||||
public ILiteCollection<Room> Rooms => _db.GetCollection<Room>("rooms");
|
||||
public ILiteCollection<SubRoom> SubRooms => _db.GetCollection<SubRoom>("subrooms");
|
||||
public ILiteCollection<AccountPresence> Presences => _db.GetCollection<AccountPresence>("presences");
|
||||
public ILiteCollection<RoomInstance> RoomInstances => _db.GetCollection<RoomInstance>("roominstances");
|
||||
public ILiteCollection<AccountSetting> Settings => _db.GetCollection<AccountSetting>("settings");
|
||||
public ILiteCollection<AccountAvatar> Avatar => _db.GetCollection<AccountAvatar>("avatar");
|
||||
public ILiteCollection<SubRoomSave> SubRoomSave => _db.GetCollection<SubRoomSave>("subroomsaves");
|
||||
public ILiteCollection<UnityAssets> UnityAssets => _db.GetCollection<UnityAssets>("unityassets");
|
||||
public ILiteCollection<ActionLink> ActionLinks => _db.GetCollection<ActionLink>("actionlinks");
|
||||
public ILiteCollection<Relationship> Relationships => _db.GetCollection<Relationship>("relationships");
|
||||
public ILiteCollection<Message> Messages => _db.GetCollection<Message>("messages");
|
||||
public ILiteCollection<SavedImage> SavedImages => _db.GetCollection<SavedImage>("savedimages");
|
||||
public ILiteCollection<AvatarSaved> AvatarSaveds => _db.GetCollection<AvatarSaved>("avatarsaveds");
|
||||
public ILiteCollection<PlayerEvent> PlayerEvents => _db.GetCollection<PlayerEvent>("playerevents");
|
||||
public ILiteCollection<PlayerInvite> PlayerInvites => _db.GetCollection<PlayerInvite>("playerinvites");
|
||||
public ILiteCollection<CustomAvatarItem> CustomAvatarItems => _db.GetCollection<CustomAvatarItem>("customavataritems");
|
||||
public ILiteCollection<Invention> Inventions => _db.GetCollection<Invention>("invention");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using DeluxeBackend.Models;
|
||||
using System.Numerics;
|
||||
using System.Security.Claims;
|
||||
using static DeluxeBackend.Enums;
|
||||
|
||||
namespace DeluxeBackend.Services
|
||||
{
|
||||
public interface IMessageService
|
||||
{
|
||||
Task<Message> SendMessage(Account fromPlayer, Account toPlayer, MessageType type, string data);
|
||||
}
|
||||
public class MessageService(ILiteDbService db, IConfiguration configuration, INotificationService ws) : IMessageService
|
||||
{
|
||||
private readonly ILiteDbService _db = db;
|
||||
private readonly IConfiguration _configuration = configuration;
|
||||
private readonly INotificationService _ws = ws;
|
||||
|
||||
|
||||
public async Task<Message> SendMessage(Account fromPlayer, Account toPlayer, MessageType type, string data)
|
||||
{
|
||||
var message = new Message
|
||||
{
|
||||
Player = toPlayer,
|
||||
FromPlayer = fromPlayer,
|
||||
Type = type,
|
||||
Data = data
|
||||
};
|
||||
|
||||
_db.Messages.Insert(message);
|
||||
|
||||
await _ws.SendToPlayer(toPlayer.Id, PushNotification.MessageReceived, message.ToDictionary());
|
||||
return message;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
using DeluxeBackend.Hubs;
|
||||
using DeluxeBackend.Services;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text.Json;
|
||||
using static DeluxeBackend.Enums;
|
||||
|
||||
namespace DeluxeBackend.Services
|
||||
{
|
||||
public interface INotificationService
|
||||
{
|
||||
Task SendToPlayer(long playerId, string id, object msg);
|
||||
Task SendToPlayer(long playerId, PushNotification id, object msg);
|
||||
Task SendToPlayerSubs(long targetPlayerId, string id, object msg);
|
||||
Task SendToAllPlayer(string id, object msg);
|
||||
Task SendToAllPlayer(PushNotification id, object msg);
|
||||
}
|
||||
|
||||
public enum PushNotification
|
||||
{
|
||||
[Token(Token = "0x4002F84")]
|
||||
RelationshipChanged = 1,
|
||||
[Token(Token = "0x4002F85")]
|
||||
MessageReceived,
|
||||
[Token(Token = "0x4002F86")]
|
||||
MessageDeleted,
|
||||
[Token(Token = "0x4002F87")]
|
||||
PresenceHeartbeatResponse,
|
||||
[Token(Token = "0x4002F88")]
|
||||
RefreshLogin,
|
||||
[Token(Token = "0x4002F89")]
|
||||
Logout,
|
||||
[Token(Token = "0x4002F8A")]
|
||||
SubscriptionUpdateProfile = 11,
|
||||
[Token(Token = "0x4002F8B")]
|
||||
SubscriptionUpdatePresence,
|
||||
[Token(Token = "0x4002F8C")]
|
||||
SubscriptionUpdateGameSession,
|
||||
[Token(Token = "0x4002F8D")]
|
||||
SubscriptionUpdateRoom = 15,
|
||||
[Token(Token = "0x4002F8E")]
|
||||
SubscriptionUpdateRoomPlaylist,
|
||||
[Token(Token = "0x4002F8F")]
|
||||
ModerationQuitGame = 20,
|
||||
[Token(Token = "0x4002F90")]
|
||||
ModerationUpdateRequired,
|
||||
[Token(Token = "0x4002F91")]
|
||||
ModerationKick,
|
||||
[Token(Token = "0x4002F92")]
|
||||
ModerationKickAttemptFailed,
|
||||
[Token(Token = "0x4002F93")]
|
||||
ModerationRoomBan,
|
||||
[Token(Token = "0x4002F94")]
|
||||
ServerMaintenance,
|
||||
[Token(Token = "0x4002F95")]
|
||||
GiftPackageReceived = 30,
|
||||
[Token(Token = "0x4002F96")]
|
||||
GiftPackageReceivedImmediate,
|
||||
[Token(Token = "0x4002F97")]
|
||||
GiftPackageRewardSelectionReceived,
|
||||
[Token(Token = "0x4002F98")]
|
||||
ProfileJuniorStatusUpdate = 40,
|
||||
[Token(Token = "0x4002F99")]
|
||||
RelationshipsInvalid = 50,
|
||||
[Token(Token = "0x4002F9A")]
|
||||
StorefrontBalanceAdd = 60,
|
||||
[Token(Token = "0x4002F9B")]
|
||||
StorefrontBalanceUpdate,
|
||||
[Token(Token = "0x4002F9C")]
|
||||
StorefrontBalancePurchase,
|
||||
[Token(Token = "0x4002F9D")]
|
||||
ConsumableMappingAdded = 70,
|
||||
[Token(Token = "0x4002F9E")]
|
||||
ConsumableMappingRemoved,
|
||||
[Token(Token = "0x4002F9F")]
|
||||
PlayerEventCreated = 80,
|
||||
[Token(Token = "0x4002FA0")]
|
||||
PlayerEventUpdated,
|
||||
[Token(Token = "0x4002FA1")]
|
||||
PlayerEventDeleted,
|
||||
[Token(Token = "0x4002FA2")]
|
||||
PlayerEventResponseChanged,
|
||||
[Token(Token = "0x4002FA3")]
|
||||
PlayerEventResponseDeleted,
|
||||
[Token(Token = "0x4002FA4")]
|
||||
PlayerEventStateChanged,
|
||||
[Token(Token = "0x4002FA5")]
|
||||
ChatMessageReceived = 90,
|
||||
[Token(Token = "0x4002FA6")]
|
||||
CommunityBoardUpdate = 95,
|
||||
[Token(Token = "0x4002FA7")]
|
||||
CommunityBoardAnnouncementUpdate,
|
||||
[Token(Token = "0x4002FA8")]
|
||||
InventionModerationStateChanged = 100,
|
||||
[Token(Token = "0x4002FA9")]
|
||||
FreeGiftButtonItemsAdded = 110,
|
||||
[Token(Token = "0x4002FAA")]
|
||||
LocalRoomKeyCreated = 120,
|
||||
[Token(Token = "0x4002FAB")]
|
||||
LocalRoomKeyDeleted
|
||||
}
|
||||
|
||||
public class NotificationService : INotificationService
|
||||
{
|
||||
private readonly IHubContext<NotificationHub> _hubContext;
|
||||
private readonly ILiteDbService _db;
|
||||
|
||||
private readonly JsonSerializerOptions _jsonOptions = new()
|
||||
{
|
||||
PropertyNamingPolicy = null
|
||||
};
|
||||
public NotificationService(IHubContext<NotificationHub> hubContext, ILiteDbService db)
|
||||
{
|
||||
_hubContext = hubContext;
|
||||
_db = db;
|
||||
}
|
||||
|
||||
private string GetJsonStr(string id, object msg)
|
||||
{
|
||||
var json = JsonSerializer.Serialize(new { Id = id, Msg = msg }, _jsonOptions);
|
||||
return json;
|
||||
}
|
||||
private string GetJsonStr(PushNotification id, object msg)
|
||||
{
|
||||
var json = JsonSerializer.Serialize(new { Id = ((int)id).ToString(), Msg = msg }, _jsonOptions);
|
||||
return json;
|
||||
}
|
||||
public async Task SendToPlayer(long playerId, string id, object msg)
|
||||
{
|
||||
await _hubContext.Clients.User(playerId.ToString()).SendAsync("Notification", GetJsonStr(id, msg));
|
||||
}
|
||||
public async Task SendToPlayer(long playerId, PushNotification id, object msg)
|
||||
{
|
||||
await _hubContext.Clients.User(playerId.ToString()).SendAsync("Notification", GetJsonStr(id, msg));
|
||||
}
|
||||
|
||||
public async Task SendToPlayerSubs(long targetPlayerId, string id, object msg)
|
||||
{
|
||||
await _hubContext.Clients.All.SendAsync("Notification", GetJsonStr(id, msg));
|
||||
|
||||
//await _hubContext.Clients.Group($"subs_{targetPlayerId}").SendAsync("Notification", GetJsonStr(id, msg));
|
||||
|
||||
//send it do yourself
|
||||
//await _hubContext.Clients.User(targetPlayerId.ToString()).SendAsync("Notification", GetJsonStr(id, msg));
|
||||
}
|
||||
|
||||
public async Task SendToAllPlayer(string id, object msg)
|
||||
{
|
||||
await _hubContext.Clients.All.SendAsync("Notification", GetJsonStr(id, msg));
|
||||
}
|
||||
public async Task SendToAllPlayer(PushNotification id, object msg)
|
||||
{
|
||||
await _hubContext.Clients.All.SendAsync("Notification", GetJsonStr(id, msg));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using System.Numerics;
|
||||
using DeluxeBackend.Models;
|
||||
|
||||
namespace DeluxeBackend.Services
|
||||
{
|
||||
public interface IPasswordService
|
||||
{
|
||||
void setPassword(Account player, string password);
|
||||
PasswordVerificationResult VerifyPassword(Account player, string passowrd);
|
||||
}
|
||||
|
||||
public class PasswordService : IPasswordService
|
||||
{
|
||||
private readonly ILiteDbService db;
|
||||
private readonly PasswordHasher<Account> _hasher = new PasswordHasher<Account>();
|
||||
|
||||
public PasswordService(ILiteDbService _db)
|
||||
{
|
||||
db = _db;
|
||||
}
|
||||
|
||||
public void setPassword(Account player, string password)
|
||||
{
|
||||
player.PasswordHash = _hasher.HashPassword(player, password);
|
||||
db.Accounts.Update(player);
|
||||
}
|
||||
|
||||
public PasswordVerificationResult VerifyPassword(Account player, string passowrd)
|
||||
{
|
||||
if (player.PasswordHash == null)
|
||||
{
|
||||
return PasswordVerificationResult.Failed;
|
||||
}
|
||||
return _hasher.VerifyHashedPassword(player, player.PasswordHash, passowrd);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user