Radicade Public Code

This commit is contained in:
JogmansonReal
2026-10-16 23:33:13 -07:00
commit 55175acdf6
832 changed files with 363261 additions and 0 deletions
+37
View File
@@ -0,0 +1,37 @@
using System.Reflection;
namespace RadicadeServer.Utils
{
public static class BuildInfo
{
public const string Tag = "notify-ids-numeric-string";
public const string NotifyIdFormat = "numeric-string";
public static readonly DateTime StartedUtc = DateTime.UtcNow;
public static DateTime? AssemblyBuiltUtc
{
get
{
try
{
var location = Assembly.GetEntryAssembly()?.Location;
return string.IsNullOrEmpty(location) || !File.Exists(location)
? null
: File.GetLastWriteTimeUtc(location);
}
catch
{
return null;
}
}
}
public static string Describe()
=> $"{Tag}: notify ids are sent as the client enum's NUMBER in a JSON string (MessageReceived=\"2\", ModerationKick=\"22\", RefreshLogin=\"5\") - " +
"never a bare number (the client cannot parse it) and never a name (it parses and matches no handler). " +
$"Started {StartedUtc:u} from an assembly published {AssemblyBuiltUtc?.ToString("u") ?? "unknown"}. " +
"If this line is missing, or the publish time is older than your deploy, the running server is not the build you just made.";
}
}
+167
View File
@@ -0,0 +1,167 @@
using System.Text;
using RadicadeServer.RecNet.Enums;
using RadicadeServer.RecNet;
using System.Buffers.Text;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
namespace RadicadeServer.Utils
{
public static class StringTools
{
public static string AltGuid(this Guid guid)
{
return guid.ToString().Replace("-", "");
}
public static string FromAES(this string encrypted, string? b64Key, string? b64IV)
{
if (string.IsNullOrEmpty(b64Key)) return "";
if (string.IsNullOrEmpty(b64IV)) return "";
try
{
byte[] cipherBytes = Convert.FromBase64String(encrypted);
byte[] keyBytes = Convert.FromBase64String(b64Key);
byte[] ivBytes = Convert.FromBase64String(b64IV);
using (Aes aes = Aes.Create())
{
aes.KeySize = 128;
aes.BlockSize = 128;
aes.Key = keyBytes;
aes.IV = ivBytes;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
using (MemoryStream ms = new MemoryStream(cipherBytes))
using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Read))
using (StreamReader sr = new StreamReader(cs, Encoding.UTF8))
{
return sr.ReadToEnd();
}
}
} catch
{
return "";
}
}
public static List<CardBoxWord> ParseCardBoxWords(this string req)
{
var split = req.Split(';', StringSplitOptions.TrimEntries);
var words = new List<CardBoxWord>();
foreach (var word in split)
{
words.Add(new CardBoxWord { Difficulty = CardDifficulty.CharadesEasy, EN_US = word });
}
return words;
}
public static string CreateTagString(List<ItemTag>? Tags)
{
if (Tags == null)
return "";
StringBuilder stringBuilder = new StringBuilder();
foreach (ItemTag itemTag in Tags)
{
stringBuilder.Append(itemTag.Tag.ToString() + "," + ((int)itemTag.Type).ToString() + "|");
}
return stringBuilder.ToString().TrimEnd('|');
}
public static string CreateTagString(string[]? Tags)
{
if (Tags == null)
return "";
StringBuilder stringBuilder = new StringBuilder();
foreach (string itemTag in Tags)
{
stringBuilder.Append(itemTag.ToString() + "," + ((int)TagType.General).ToString() + "|");
}
return stringBuilder.ToString().TrimEnd('|');
}
public static List<ItemTag> ReadTags(string Tags)
{
List<ItemTag> list = new List<ItemTag>();
if (string.IsNullOrWhiteSpace(Tags)) return list;
string[] tags = Tags.Split("|", StringSplitOptions.None);
foreach (string text in tags)
{
string[] array3 = text.Split(",", StringSplitOptions.None);
if (array3.Length != 2) continue;
if (!int.TryParse(array3[1], out var typeValue) || !Enum.IsDefined(typeof(TagType), typeValue))
continue;
list.Add(new ItemTag
{
Tag = array3[0],
Type = (TagType)typeValue
});
}
return list;
}
public static List<string> TagsToStrings(List<ItemTag> Tags)
{
List<string> list = new List<string>();
foreach (var tag in Tags)
{
list.Add(tag.Tag);
}
return list;
}
public static string ToBase64(this string str)
{
var bytes = System.Text.Encoding.UTF8.GetBytes(str);
var b64 = Convert.ToBase64String(bytes);
return b64;
}
private static string[] BlacklistedWords = {
"nigger",
"nigga",
"faggot",
"fag",
"nigg",
};
private static string[] BlacklistedTags = {
"rro",
"featured"
};
public static string Sanitize(this string str)
{
foreach (var tag in BlacklistedWords)
{
str = Regex.Replace(str, tag, "****", RegexOptions.IgnoreCase);
}
return str;
}
public static bool IsPure(this string str)
{
if (string.IsNullOrEmpty(str)) return true;
foreach (var tag in BlacklistedWords)
{
if (Regex.IsMatch(str, tag, RegexOptions.IgnoreCase))
return false;
}
return true;
}
public static bool TagAllowed(this string str)
{
foreach (var tag in BlacklistedTags) {
if (Regex.IsMatch(tag, str))
return false;
}
return str.IsPure();
}
}
}
+155
View File
@@ -0,0 +1,155 @@
using Microsoft.EntityFrameworkCore;
using RadicadeServer.API.Notifications;
using RadicadeServer.DB;
using RadicadeServer.RecNet.Enums.Messages;
using RadicadeServer.RecNet.Enums.Moderation;
using RadicadeServer.RecNet.Messages;
using RadicadeServer.RecNet.Moderation;
using RadicadeServer.RecNet.Notifications;
namespace RadicadeServer.Utils
{
public static class VoiceChatRestrictions
{
public const string NotificationId = "VoiceChatRestriction";
public const string Method = "Voice Restriction";
public const long CoachAccountId = 1;
public const string CoachMessage =
"You have had your voice privileges temporarily restricted due to speech which violates the Code of Conduct.";
public static readonly TimeSpan DefaultDuration = TimeSpan.FromHours(24);
public static readonly TimeSpan MinimumDuration = TimeSpan.FromHours(1);
public static readonly TimeSpan MaximumDuration = TimeSpan.FromDays(30);
public static TimeSpan ClampDuration(TimeSpan duration)
{
if (duration < MinimumDuration) return MinimumDuration;
if (duration > MaximumDuration) return MaximumDuration;
return duration;
}
public static Task<VoiceChatRestriction?> ActiveAsync(RecDBContext db, long playerId) =>
db.VoiceChatRestrictions.AsNoTracking()
.Where(x => x.PlayerId == playerId && x.ClearedAt == null && x.ExpiresAt > DateTime.UtcNow)
.OrderByDescending(x => x.ExpiresAt)
.FirstOrDefaultAsync();
public static async Task<bool> IsRestrictedAsync(RecDBContext db, long playerId) =>
await ActiveAsync(db, playerId) != null;
public static async Task<VoiceChatRestriction> ApplyAsync(
RecDBContext db,
long playerId,
string reason,
ReportCategory category,
TimeSpan duration,
string issuedBy,
string? issuedByUsername = null,
string? moderatorNote = null)
{
var now = DateTime.UtcNow;
var clamped = ClampDuration(duration);
var restriction = await db.VoiceChatRestrictions
.Where(x => x.PlayerId == playerId && x.ClearedAt == null && x.ExpiresAt > now)
.OrderByDescending(x => x.ExpiresAt)
.FirstOrDefaultAsync();
if (restriction == null)
{
restriction = new VoiceChatRestriction
{
PlayerId = playerId,
StartedAt = now,
ExpiresAt = now + clamped
};
await db.VoiceChatRestrictions.AddAsync(restriction);
}
else
{
var extended = now + clamped;
if (extended > restriction.ExpiresAt) restriction.ExpiresAt = extended;
restriction.StartedAt = now;
}
restriction.Reason = reason;
restriction.Category = category;
restriction.IssuedBy = issuedBy;
restriction.IssuedByUsername = issuedByUsername;
restriction.ModeratorNote = moderatorNote;
await db.SaveChangesAsync();
await TellPlayerAsync(playerId);
return restriction;
}
private static async Task TellPlayerAsync(long playerId)
{
try
{
await Notify.SendMessage(playerId, new Message
{
Type = MessageType.CoachMessage,
Data = CoachMessage,
FromPlayerId = CoachAccountId
});
}
catch
{
}
}
public static async Task<bool> ClearAsync(RecDBContext db, long playerId, string? clearedBy = null)
{
var now = DateTime.UtcNow;
var active = await db.VoiceChatRestrictions
.Where(x => x.PlayerId == playerId && x.ClearedAt == null && x.ExpiresAt > now)
.ToListAsync();
if (active.Count == 0) return false;
foreach (var restriction in active)
{
restriction.ClearedAt = now;
restriction.ClearedBy = clearedBy;
}
await db.SaveChangesAsync();
return true;
}
public static object Payload(VoiceChatRestriction? restriction) => new
{
restricted = restriction != null,
playerId = restriction?.PlayerId ?? 0,
reason = restriction?.Reason ?? "",
category = restriction?.Category.ToString() ?? "",
startedAtUtc = restriction?.StartedAt,
expiresAtUtc = restriction?.ExpiresAt,
secondsRemaining = restriction == null
? 0
: (int)Math.Max(0, (restriction.ExpiresAt - DateTime.UtcNow).TotalSeconds)
};
public static async Task PushAsync(long playerId, VoiceChatRestriction? restriction)
{
try
{
await Notify.SendNotify(playerId, new Notification
{
Id = NotificationId,
Msg = Payload(restriction)
});
}
catch
{
}
}
}
}