♻️ I have no idea what am I doing. Might be mixing stuff

This commit is contained in:
2025-07-14 19:55:28 +08:00
parent ef9175d27d
commit cbfdb4aa60
232 changed files with 990 additions and 115807 deletions

View File

@@ -0,0 +1,40 @@
using System.Text;
using System.Globalization;
using System.Text.RegularExpressions;
namespace DysonNetwork.Shared.Content;
public abstract partial class TextSanitizer
{
[GeneratedRegex(@"[\u0000-\u001F\u007F\u200B-\u200F\u202A-\u202E\u2060-\u206F\uFFF0-\uFFFF]")]
private static partial Regex WeirdUnicodeRegex();
[GeneratedRegex(@"[\r\n]+")]
private static partial Regex NewlineRegex();
public static string? Sanitize(string? text)
{
if (text is null) return null;
// Normalize weird Unicode characters
var cleaned = WeirdUnicodeRegex().Replace(text, "");
// Normalize bold/italic/fancy unicode letters to ASCII
cleaned = NormalizeFancyUnicode(cleaned);
// Replace multiple newlines with a single newline
cleaned = NewlineRegex().Replace(cleaned, "\n");
return cleaned;
}
private static string NormalizeFancyUnicode(string input)
{
var sb = new StringBuilder(input.Length);
foreach (var c in input.Normalize(NormalizationForm.FormKC).Where(c =>
char.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark))
sb.Append(c);
return sb.ToString();
}
}

View File

@@ -0,0 +1,19 @@
using System.Globalization;
using DysonNetwork.Shared.Proto;
namespace DysonNetwork.Shared;
public static class CultureService
{
public static void SetCultureInfo(string? languageCode)
{
var info = new CultureInfo(languageCode ?? "en-us", false);
CultureInfo.CurrentCulture = info;
CultureInfo.CurrentUICulture = info;
}
public static void SetCultureInfo(Account account)
{
SetCultureInfo(account.Language);
}
}

View File

@@ -3,6 +3,23 @@ using Google.Protobuf.WellKnownTypes;
namespace DysonNetwork.Shared.Data;
public enum ContentSensitiveMark
{
Language,
SexualContent,
Violence,
Profanity,
HateSpeech,
Racism,
AdultContent,
DrugAbuse,
AlcoholAbuse,
Gambling,
SelfHarm,
ChildAbuse,
Other
}
/// <summary>
/// The class that used in jsonb columns which referenced the cloud file.
/// The aim of this class is to store some properties that won't change to a file to reduce the database load.

View File

@@ -0,0 +1,50 @@
using System.ComponentModel.DataAnnotations;
namespace DysonNetwork.Shared.Data;
/// <summary>
/// The verification info of a resource
/// stands, for it is really an individual or organization or a company in the real world.
/// Besides, it can also be use for mark parody or fake.
/// </summary>
public class VerificationMark
{
public VerificationMarkType Type { get; set; }
[MaxLength(1024)] public string? Title { get; set; }
[MaxLength(8192)] public string? Description { get; set; }
[MaxLength(1024)] public string? VerifiedBy { get; set; }
public Shared.Proto.VerificationMark ToProtoValue()
{
var proto = new Shared.Proto.VerificationMark
{
Type = Type switch
{
VerificationMarkType.Official => Shared.Proto.VerificationMarkType.Official,
VerificationMarkType.Individual => Shared.Proto.VerificationMarkType.Individual,
VerificationMarkType.Organization => Shared.Proto.VerificationMarkType.Organization,
VerificationMarkType.Government => Shared.Proto.VerificationMarkType.Government,
VerificationMarkType.Creator => Shared.Proto.VerificationMarkType.Creator,
VerificationMarkType.Developer => Shared.Proto.VerificationMarkType.Developer,
VerificationMarkType.Parody => Shared.Proto.VerificationMarkType.Parody,
_ => Shared.Proto.VerificationMarkType.Unspecified
},
Title = Title ?? string.Empty,
Description = Description ?? string.Empty,
VerifiedBy = VerifiedBy ?? string.Empty
};
return proto;
}
}
public enum VerificationMarkType
{
Official,
Individual,
Organization,
Government,
Creator,
Developer,
Parody
}

View File

@@ -73,4 +73,28 @@ public static class GrpcClientHelper
return new PusherService.PusherServiceClient(CreateCallInvoker(url, clientCertPath, clientKeyPath,
clientCertPassword));
}
public static async Task<FileService.FileServiceClient> CreateFileServiceClient(
IEtcdClient etcdClient,
string clientCertPath,
string clientKeyPath,
string? clientCertPassword = null
)
{
var url = await GetServiceUrlFromEtcd(etcdClient, "DysonNetwork.File");
return new FileService.FileServiceClient(CreateCallInvoker(url, clientCertPath, clientKeyPath,
clientCertPassword));
}
public static async Task<FileReferenceService.FileReferenceServiceClient> CreateFileReferenceServiceClient(
IEtcdClient etcdClient,
string clientCertPath,
string clientKeyPath,
string? clientCertPassword = null
)
{
var url = await GetServiceUrlFromEtcd(etcdClient, "DysonNetwork.FileReference");
return new FileReferenceService.FileReferenceServiceClient(CreateCallInvoker(url, clientCertPath, clientKeyPath,
clientCertPassword));
}
}

View File

@@ -20,7 +20,7 @@ message Account {
string language = 4;
google.protobuf.Timestamp activated_at = 5;
bool is_superuser = 6;
AccountProfile profile = 7;
repeated AccountContact contacts = 8;
repeated AccountBadge badges = 9;
@@ -43,17 +43,17 @@ message AccountProfile {
google.protobuf.StringValue location = 9;
google.protobuf.Timestamp birthday = 10;
google.protobuf.Timestamp last_seen_at = 11;
VerificationMark verification = 12;
BadgeReferenceObject active_badge = 13;
int32 experience = 14;
int32 level = 15;
double leveling_progress = 16;
CloudFile picture = 19;
CloudFile background = 20;
string account_id = 21;
}
@@ -155,24 +155,15 @@ message BadgeReferenceObject {
// Relationship represents a connection between two accounts
message Relationship {
string id = 1;
string from_account_id = 2;
string to_account_id = 3;
RelationshipType type = 4;
string note = 5;
string account_id = 1;
string related_id = 2;
optional Account account = 3;
optional Account related = 4;
int32 type = 5;
google.protobuf.Timestamp created_at = 6;
google.protobuf.Timestamp updated_at = 7;
}
// Enum for relationship types
enum RelationshipType {
RELATIONSHIP_TYPE_UNSPECIFIED = 0;
FRIEND = 1;
BLOCKED = 2;
PENDING_INCOMING = 3;
PENDING_OUTGOING = 4;
}
// Leveling information
message LevelingInfo {
int32 current_level = 1;
@@ -192,43 +183,30 @@ service AccountService {
// Account Operations
rpc GetAccount(GetAccountRequest) returns (Account) {}
rpc GetAccountBatch(GetAccountBatchRequest) returns (GetAccountBatchResponse) {}
rpc CreateAccount(CreateAccountRequest) returns (Account) {}
rpc UpdateAccount(UpdateAccountRequest) returns (Account) {}
rpc DeleteAccount(DeleteAccountRequest) returns (google.protobuf.Empty) {}
rpc ListAccounts(ListAccountsRequest) returns (ListAccountsResponse) {}
// Profile Operations
rpc GetProfile(GetProfileRequest) returns (AccountProfile) {}
rpc UpdateProfile(UpdateProfileRequest) returns (AccountProfile) {}
// Contact Operations
rpc AddContact(AddContactRequest) returns (AccountContact) {}
rpc UpdateContact(UpdateContactRequest) returns (AccountContact) {}
rpc RemoveContact(RemoveContactRequest) returns (google.protobuf.Empty) {}
rpc ListContacts(ListContactsRequest) returns (ListContactsResponse) {}
rpc VerifyContact(VerifyContactRequest) returns (AccountContact) {}
// Badge Operations
rpc AddBadge(AddBadgeRequest) returns (AccountBadge) {}
rpc RemoveBadge(RemoveBadgeRequest) returns (google.protobuf.Empty) {}
rpc ListBadges(ListBadgesRequest) returns (ListBadgesResponse) {}
rpc SetActiveBadge(SetActiveBadgeRequest) returns (AccountProfile) {}
// Authentication Factor Operations
rpc AddAuthFactor(AddAuthFactorRequest) returns (AccountAuthFactor) {}
rpc RemoveAuthFactor(RemoveAuthFactorRequest) returns (google.protobuf.Empty) {}
rpc ListAuthFactors(ListAuthFactorsRequest) returns (ListAuthFactorsResponse) {}
// Connection Operations
rpc AddConnection(AddConnectionRequest) returns (AccountConnection) {}
rpc RemoveConnection(RemoveConnectionRequest) returns (google.protobuf.Empty) {}
rpc ListConnections(ListConnectionsRequest) returns (ListConnectionsResponse) {}
// Relationship Operations
rpc CreateRelationship(CreateRelationshipRequest) returns (Relationship) {}
rpc UpdateRelationship(UpdateRelationshipRequest) returns (Relationship) {}
rpc DeleteRelationship(DeleteRelationshipRequest) returns (google.protobuf.Empty) {}
rpc ListRelationships(ListRelationshipsRequest) returns (ListRelationshipsResponse) {}
rpc GetRelationship(GetRelationshipRequest) returns (GetRelationshipResponse) {}
rpc HasRelationship(GetRelationshipRequest) returns (google.protobuf.BoolValue) {}
rpc ListFriends(ListUserRelationshipSimpleRequest) returns (ListUserRelationshipSimpleResponse) {}
rpc ListBlocked(ListUserRelationshipSimpleRequest) returns (ListUserRelationshipSimpleResponse) {}
}
// ====================================
@@ -301,18 +279,6 @@ message AddContactRequest {
bool is_primary = 4; // If this should be the primary contact
}
message UpdateContactRequest {
string id = 1; // Contact ID to update
string account_id = 2; // Account ID (for validation)
google.protobuf.StringValue content = 3; // New contact content
google.protobuf.BoolValue is_primary = 4; // New primary status
}
message RemoveContactRequest {
string id = 1; // Contact ID to remove
string account_id = 2; // Account ID (for validation)
}
message ListContactsRequest {
string account_id = 1; // Account ID to list contacts for
AccountContactType type = 2; // Optional: filter by type
@@ -330,20 +296,6 @@ message VerifyContactRequest {
}
// Badge Requests/Responses
message AddBadgeRequest {
string account_id = 1; // Account to add badge to
string type = 2; // Type of badge
google.protobuf.StringValue label = 3; // Display label
google.protobuf.StringValue caption = 4; // Description
map<string, string> meta = 5; // Additional metadata
google.protobuf.Timestamp expired_at = 6; // Optional expiration
}
message RemoveBadgeRequest {
string id = 1; // Badge ID to remove
string account_id = 2; // Account ID (for validation)
}
message ListBadgesRequest {
string account_id = 1; // Account to list badges for
string type = 2; // Optional: filter by type
@@ -354,26 +306,6 @@ message ListBadgesResponse {
repeated AccountBadge badges = 1; // List of badges
}
message SetActiveBadgeRequest {
string account_id = 1; // Account to update
string badge_id = 2; // Badge ID to set as active (empty to clear)
}
// Authentication Factor Requests/Responses
message AddAuthFactorRequest {
string account_id = 1; // Account to add factor to
AccountAuthFactorType type = 2; // Type of factor
string secret = 3; // Factor secret (hashed on server)
map<string, string> config = 4; // Configuration
int32 trustworthy = 5; // Trust level
google.protobuf.Timestamp expired_at = 6; // Optional expiration
}
message RemoveAuthFactorRequest {
string id = 1; // Factor ID to remove
string account_id = 2; // Account ID (for validation)
}
message ListAuthFactorsRequest {
string account_id = 1; // Account to list factors for
bool active_only = 2; // Only return active (non-expired) factors
@@ -383,21 +315,6 @@ message ListAuthFactorsResponse {
repeated AccountAuthFactor factors = 1; // List of auth factors
}
// Connection Requests/Responses
message AddConnectionRequest {
string account_id = 1; // Account to add connection to
string provider = 2; // Provider name (e.g., "google", "github")
string provided_identifier = 3; // Provider's user ID
map<string, string> meta = 4; // Additional metadata
google.protobuf.StringValue access_token = 5; // OAuth access token
google.protobuf.StringValue refresh_token = 6; // OAuth refresh token
}
message RemoveConnectionRequest {
string id = 1; // Connection ID to remove
string account_id = 2; // Account ID (for validation)
}
message ListConnectionsRequest {
string account_id = 1; // Account to list connections for
string provider = 2; // Optional: filter by provider
@@ -408,30 +325,9 @@ message ListConnectionsResponse {
}
// Relationship Requests/Responses
message CreateRelationshipRequest {
string from_account_id = 1; // Source account ID
string to_account_id = 2; // Target account ID
RelationshipType type = 3; // Type of relationship
string note = 4; // Optional note
}
message UpdateRelationshipRequest {
string id = 1; // Relationship ID to update
string account_id = 2; // Account ID (for validation)
RelationshipType type = 3; // New relationship type
google.protobuf.StringValue note = 4; // New note
}
message DeleteRelationshipRequest {
string id = 1; // Relationship ID to delete
string account_id = 2; // Account ID (for validation)
}
message ListRelationshipsRequest {
string account_id = 1; // Account to list relationships for
RelationshipType type = 2; // Optional: filter by type
bool incoming = 3; // If true, list incoming relationships
bool outgoing = 4; // If true, list outgoing relationships
optional int32 status = 2; // Filter by status
int32 page_size = 5; // Number of results per page
string page_token = 6; // Token for pagination
}
@@ -442,3 +338,20 @@ message ListRelationshipsResponse {
int32 total_size = 3; // Total number of relationships
}
message GetRelationshipRequest {
string account_id = 1;
string related_id = 2;
optional int32 status = 3;
}
message GetRelationshipResponse {
optional Relationship relationship = 1;
}
message ListUserRelationshipSimpleRequest {
string account_id = 1;
}
message ListUserRelationshipSimpleResponse {
repeated string accounts_id = 1;
}

View File

@@ -65,6 +65,9 @@ enum ChallengePlatform {
service AuthService {
rpc Authenticate(AuthenticateRequest) returns (AuthenticateResponse) {}
rpc ValidatePin(ValidatePinRequest) returns (ValidateResponse) {}
rpc ValidateCaptcha(ValidateCaptchaRequest) returns (ValidateResponse) {}
}
message AuthenticateRequest {
@@ -77,6 +80,19 @@ message AuthenticateResponse {
optional AuthSession session = 3;
}
message ValidatePinRequest {
string account_id = 1;
string pin = 2;
}
message ValidateCaptchaRequest {
string token = 1;
}
message ValidateResponse {
bool valid = 1;
}
// Permission related messages and services
message PermissionNode {
string id = 1;

View File

@@ -51,6 +51,7 @@ message CloudFile {
service FileService {
// Get file reference by ID
rpc GetFile(GetFileRequest) returns (CloudFile);
rpc GetFileBatch(GetFileBatchRequest) returns (GetFileBatchResponse);
// Update an existing file reference
rpc UpdateFile(UpdateFileRequest) returns (CloudFile);
@@ -73,6 +74,14 @@ message GetFileRequest {
string id = 1;
}
message GetFileBatchRequest {
repeated string ids = 1;
}
message GetFileBatchResponse {
repeated CloudFile files = 1;
}
// Request message for UpdateFile
message UpdateFileRequest {
CloudFile file = 1;
@@ -157,6 +166,18 @@ message CreateReferenceRequest {
optional google.protobuf.Duration duration = 5; // Alternative to expired_at
}
message CreateReferenceBatchRequest {
repeated string files_id = 1;
string usage = 2;
string resource_id = 3;
optional google.protobuf.Timestamp expired_at = 4;
optional google.protobuf.Duration duration = 5; // Alternative to expired_at
}
message CreateReferenceBatchResponse {
repeated CloudFileReference references = 1;
}
message GetReferencesRequest {
string file_id = 1;
}
@@ -239,6 +260,7 @@ message HasFileReferencesResponse {
service FileReferenceService {
// Creates a new reference to a file for a specific resource
rpc CreateReference(CreateReferenceRequest) returns (CloudFileReference);
rpc CreateReferenceBatch(CreateReferenceBatchRequest) returns (CreateReferenceBatchResponse);
// Gets all references to a file
rpc GetReferences(GetReferencesRequest) returns (GetReferencesResponse);

View File

@@ -44,4 +44,37 @@ public static class ServiceHelper
return services;
}
public static IServiceCollection AddDriveService(this IServiceCollection services)
{
services.AddSingleton<FileService.FileServiceClient>(sp =>
{
var etcdClient = sp.GetRequiredService<IEtcdClient>();
var config = sp.GetRequiredService<IConfiguration>();
var clientCertPath = config["Service:ClientCert"]!;
var clientKeyPath = config["Service:ClientKey"]!;
var clientCertPassword = config["Service:CertPassword"];
return GrpcClientHelper
.CreateFileServiceClient(etcdClient, clientCertPath, clientKeyPath, clientCertPassword)
.GetAwaiter()
.GetResult();
});
services.AddSingleton<FileReferenceService.FileReferenceServiceClient>(sp =>
{
var etcdClient = sp.GetRequiredService<IEtcdClient>();
var config = sp.GetRequiredService<IConfiguration>();
var clientCertPath = config["Service:ClientCert"]!;
var clientKeyPath = config["Service:ClientKey"]!;
var clientCertPassword = config["Service:CertPassword"];
return GrpcClientHelper
.CreateFileReferenceServiceClient(etcdClient, clientCertPath, clientKeyPath, clientCertPassword)
.GetAwaiter()
.GetResult();
});
return services;
}
}