15 Commits

45 changed files with 1043 additions and 180 deletions

View File

@@ -3,11 +3,21 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="CppAst.CodeGen" Version="0.4.1" />
<PackageVersion Include="dotenv.net" Version="3.2.0" />
<PackageVersion Include="JsonSubTypes" Version="2.0.1" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.16" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Ini" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Polly" Version="8.1.0" />
<PackageVersion Include="RestSharp" Version="112.1.0" />
<PackageVersion Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageVersion Include="Tomlyn.Extensions.Configuration" Version="1.0.6" />
<PackageVersion Include="Tomlyn" Version="0.17.0" />
</ItemGroup>
</Project>

View File

@@ -7,9 +7,21 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tribufu.Generated", "src\Tr
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tribufu.Example", "src\Tribufu.Example\Tribufu.Example.csproj", "{D6392A29-E2DC-4050-B4C1-B279DD2D226D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tribufu.Logging", "src\Tribufu.Logging\Tribufu.Logging.csproj", "{CFD80847-9B98-4991-BADF-8714E7D8D81C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tribufu.SafeCheck", "src\Tribufu.SafeCheck\Tribufu.SafeCheck.csproj", "{B1463692-23C0-435B-A018-B6ED8F305E8D}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tribufu.Configuration", "src\Tribufu.Configuration\Tribufu.Configuration.csproj", "{C0A841C8-9FC5-4AC0-B9AD-6BBFCEDCBE5F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tribufu.Platform", "src\Tribufu.Platform\Tribufu.Platform.csproj", "{26EEB407-733C-4383-9211-B083CD5F593B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tribufu.Database", "src\Tribufu.Database\Tribufu.Database.csproj", "{E7F9A76F-C087-410B-B4B5-A928A6CDC2BA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tribufu.Serialization", "src\Tribufu.Serialization\Tribufu.Serialization.csproj", "{D6DAE078-2F80-49DD-97A3-B1223FE04F91}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tribufu.ComponentModel", "src\Tribufu.ComponentModel\Tribufu.ComponentModel.csproj", "{7CB04FFD-8F4B-4B40-BB4B-2BAA19D783E1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tribufu.Native", "src\Tribufu.Native\Tribufu.Native.csproj", "{A7388573-2EEA-449D-8605-9115BE8C0050}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tribufu.Native.Generator", "src\Tribufu.Native.Generator\Tribufu.Native.Generator.csproj", "{F71217EC-9ED2-40B9-B0B8-7696FA280889}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -57,23 +69,104 @@ Global
{D6392A29-E2DC-4050-B4C1-B279DD2D226D}.Release|x64.Build.0 = Release|Any CPU
{D6392A29-E2DC-4050-B4C1-B279DD2D226D}.Release|x86.ActiveCfg = Release|Any CPU
{D6392A29-E2DC-4050-B4C1-B279DD2D226D}.Release|x86.Build.0 = Release|Any CPU
{B1463692-23C0-435B-A018-B6ED8F305E8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B1463692-23C0-435B-A018-B6ED8F305E8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B1463692-23C0-435B-A018-B6ED8F305E8D}.Debug|x64.ActiveCfg = Debug|Any CPU
{B1463692-23C0-435B-A018-B6ED8F305E8D}.Debug|x64.Build.0 = Debug|Any CPU
{B1463692-23C0-435B-A018-B6ED8F305E8D}.Debug|x86.ActiveCfg = Debug|Any CPU
{B1463692-23C0-435B-A018-B6ED8F305E8D}.Debug|x86.Build.0 = Debug|Any CPU
{B1463692-23C0-435B-A018-B6ED8F305E8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B1463692-23C0-435B-A018-B6ED8F305E8D}.Release|Any CPU.Build.0 = Release|Any CPU
{B1463692-23C0-435B-A018-B6ED8F305E8D}.Release|x64.ActiveCfg = Release|Any CPU
{B1463692-23C0-435B-A018-B6ED8F305E8D}.Release|x64.Build.0 = Release|Any CPU
{B1463692-23C0-435B-A018-B6ED8F305E8D}.Release|x86.ActiveCfg = Release|Any CPU
{B1463692-23C0-435B-A018-B6ED8F305E8D}.Release|x86.Build.0 = Release|Any CPU
{CFD80847-9B98-4991-BADF-8714E7D8D81C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CFD80847-9B98-4991-BADF-8714E7D8D81C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CFD80847-9B98-4991-BADF-8714E7D8D81C}.Debug|x64.ActiveCfg = Debug|Any CPU
{CFD80847-9B98-4991-BADF-8714E7D8D81C}.Debug|x64.Build.0 = Debug|Any CPU
{CFD80847-9B98-4991-BADF-8714E7D8D81C}.Debug|x86.ActiveCfg = Debug|Any CPU
{CFD80847-9B98-4991-BADF-8714E7D8D81C}.Debug|x86.Build.0 = Debug|Any CPU
{CFD80847-9B98-4991-BADF-8714E7D8D81C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CFD80847-9B98-4991-BADF-8714E7D8D81C}.Release|Any CPU.Build.0 = Release|Any CPU
{CFD80847-9B98-4991-BADF-8714E7D8D81C}.Release|x64.ActiveCfg = Release|Any CPU
{CFD80847-9B98-4991-BADF-8714E7D8D81C}.Release|x64.Build.0 = Release|Any CPU
{CFD80847-9B98-4991-BADF-8714E7D8D81C}.Release|x86.ActiveCfg = Release|Any CPU
{CFD80847-9B98-4991-BADF-8714E7D8D81C}.Release|x86.Build.0 = Release|Any CPU
{C0A841C8-9FC5-4AC0-B9AD-6BBFCEDCBE5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C0A841C8-9FC5-4AC0-B9AD-6BBFCEDCBE5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C0A841C8-9FC5-4AC0-B9AD-6BBFCEDCBE5F}.Debug|x64.ActiveCfg = Debug|Any CPU
{C0A841C8-9FC5-4AC0-B9AD-6BBFCEDCBE5F}.Debug|x64.Build.0 = Debug|Any CPU
{C0A841C8-9FC5-4AC0-B9AD-6BBFCEDCBE5F}.Debug|x86.ActiveCfg = Debug|Any CPU
{C0A841C8-9FC5-4AC0-B9AD-6BBFCEDCBE5F}.Debug|x86.Build.0 = Debug|Any CPU
{C0A841C8-9FC5-4AC0-B9AD-6BBFCEDCBE5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C0A841C8-9FC5-4AC0-B9AD-6BBFCEDCBE5F}.Release|Any CPU.Build.0 = Release|Any CPU
{C0A841C8-9FC5-4AC0-B9AD-6BBFCEDCBE5F}.Release|x64.ActiveCfg = Release|Any CPU
{C0A841C8-9FC5-4AC0-B9AD-6BBFCEDCBE5F}.Release|x64.Build.0 = Release|Any CPU
{C0A841C8-9FC5-4AC0-B9AD-6BBFCEDCBE5F}.Release|x86.ActiveCfg = Release|Any CPU
{C0A841C8-9FC5-4AC0-B9AD-6BBFCEDCBE5F}.Release|x86.Build.0 = Release|Any CPU
{26EEB407-733C-4383-9211-B083CD5F593B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{26EEB407-733C-4383-9211-B083CD5F593B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{26EEB407-733C-4383-9211-B083CD5F593B}.Debug|x64.ActiveCfg = Debug|Any CPU
{26EEB407-733C-4383-9211-B083CD5F593B}.Debug|x64.Build.0 = Debug|Any CPU
{26EEB407-733C-4383-9211-B083CD5F593B}.Debug|x86.ActiveCfg = Debug|Any CPU
{26EEB407-733C-4383-9211-B083CD5F593B}.Debug|x86.Build.0 = Debug|Any CPU
{26EEB407-733C-4383-9211-B083CD5F593B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{26EEB407-733C-4383-9211-B083CD5F593B}.Release|Any CPU.Build.0 = Release|Any CPU
{26EEB407-733C-4383-9211-B083CD5F593B}.Release|x64.ActiveCfg = Release|Any CPU
{26EEB407-733C-4383-9211-B083CD5F593B}.Release|x64.Build.0 = Release|Any CPU
{26EEB407-733C-4383-9211-B083CD5F593B}.Release|x86.ActiveCfg = Release|Any CPU
{26EEB407-733C-4383-9211-B083CD5F593B}.Release|x86.Build.0 = Release|Any CPU
{E7F9A76F-C087-410B-B4B5-A928A6CDC2BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E7F9A76F-C087-410B-B4B5-A928A6CDC2BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E7F9A76F-C087-410B-B4B5-A928A6CDC2BA}.Debug|x64.ActiveCfg = Debug|Any CPU
{E7F9A76F-C087-410B-B4B5-A928A6CDC2BA}.Debug|x64.Build.0 = Debug|Any CPU
{E7F9A76F-C087-410B-B4B5-A928A6CDC2BA}.Debug|x86.ActiveCfg = Debug|Any CPU
{E7F9A76F-C087-410B-B4B5-A928A6CDC2BA}.Debug|x86.Build.0 = Debug|Any CPU
{E7F9A76F-C087-410B-B4B5-A928A6CDC2BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E7F9A76F-C087-410B-B4B5-A928A6CDC2BA}.Release|Any CPU.Build.0 = Release|Any CPU
{E7F9A76F-C087-410B-B4B5-A928A6CDC2BA}.Release|x64.ActiveCfg = Release|Any CPU
{E7F9A76F-C087-410B-B4B5-A928A6CDC2BA}.Release|x64.Build.0 = Release|Any CPU
{E7F9A76F-C087-410B-B4B5-A928A6CDC2BA}.Release|x86.ActiveCfg = Release|Any CPU
{E7F9A76F-C087-410B-B4B5-A928A6CDC2BA}.Release|x86.Build.0 = Release|Any CPU
{D6DAE078-2F80-49DD-97A3-B1223FE04F91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D6DAE078-2F80-49DD-97A3-B1223FE04F91}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D6DAE078-2F80-49DD-97A3-B1223FE04F91}.Debug|x64.ActiveCfg = Debug|Any CPU
{D6DAE078-2F80-49DD-97A3-B1223FE04F91}.Debug|x64.Build.0 = Debug|Any CPU
{D6DAE078-2F80-49DD-97A3-B1223FE04F91}.Debug|x86.ActiveCfg = Debug|Any CPU
{D6DAE078-2F80-49DD-97A3-B1223FE04F91}.Debug|x86.Build.0 = Debug|Any CPU
{D6DAE078-2F80-49DD-97A3-B1223FE04F91}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D6DAE078-2F80-49DD-97A3-B1223FE04F91}.Release|Any CPU.Build.0 = Release|Any CPU
{D6DAE078-2F80-49DD-97A3-B1223FE04F91}.Release|x64.ActiveCfg = Release|Any CPU
{D6DAE078-2F80-49DD-97A3-B1223FE04F91}.Release|x64.Build.0 = Release|Any CPU
{D6DAE078-2F80-49DD-97A3-B1223FE04F91}.Release|x86.ActiveCfg = Release|Any CPU
{D6DAE078-2F80-49DD-97A3-B1223FE04F91}.Release|x86.Build.0 = Release|Any CPU
{7CB04FFD-8F4B-4B40-BB4B-2BAA19D783E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7CB04FFD-8F4B-4B40-BB4B-2BAA19D783E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7CB04FFD-8F4B-4B40-BB4B-2BAA19D783E1}.Debug|x64.ActiveCfg = Debug|Any CPU
{7CB04FFD-8F4B-4B40-BB4B-2BAA19D783E1}.Debug|x64.Build.0 = Debug|Any CPU
{7CB04FFD-8F4B-4B40-BB4B-2BAA19D783E1}.Debug|x86.ActiveCfg = Debug|Any CPU
{7CB04FFD-8F4B-4B40-BB4B-2BAA19D783E1}.Debug|x86.Build.0 = Debug|Any CPU
{7CB04FFD-8F4B-4B40-BB4B-2BAA19D783E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7CB04FFD-8F4B-4B40-BB4B-2BAA19D783E1}.Release|Any CPU.Build.0 = Release|Any CPU
{7CB04FFD-8F4B-4B40-BB4B-2BAA19D783E1}.Release|x64.ActiveCfg = Release|Any CPU
{7CB04FFD-8F4B-4B40-BB4B-2BAA19D783E1}.Release|x64.Build.0 = Release|Any CPU
{7CB04FFD-8F4B-4B40-BB4B-2BAA19D783E1}.Release|x86.ActiveCfg = Release|Any CPU
{7CB04FFD-8F4B-4B40-BB4B-2BAA19D783E1}.Release|x86.Build.0 = Release|Any CPU
{A7388573-2EEA-449D-8605-9115BE8C0050}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A7388573-2EEA-449D-8605-9115BE8C0050}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A7388573-2EEA-449D-8605-9115BE8C0050}.Debug|x64.ActiveCfg = Debug|Any CPU
{A7388573-2EEA-449D-8605-9115BE8C0050}.Debug|x64.Build.0 = Debug|Any CPU
{A7388573-2EEA-449D-8605-9115BE8C0050}.Debug|x86.ActiveCfg = Debug|Any CPU
{A7388573-2EEA-449D-8605-9115BE8C0050}.Debug|x86.Build.0 = Debug|Any CPU
{A7388573-2EEA-449D-8605-9115BE8C0050}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A7388573-2EEA-449D-8605-9115BE8C0050}.Release|Any CPU.Build.0 = Release|Any CPU
{A7388573-2EEA-449D-8605-9115BE8C0050}.Release|x64.ActiveCfg = Release|Any CPU
{A7388573-2EEA-449D-8605-9115BE8C0050}.Release|x64.Build.0 = Release|Any CPU
{A7388573-2EEA-449D-8605-9115BE8C0050}.Release|x86.ActiveCfg = Release|Any CPU
{A7388573-2EEA-449D-8605-9115BE8C0050}.Release|x86.Build.0 = Release|Any CPU
{F71217EC-9ED2-40B9-B0B8-7696FA280889}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F71217EC-9ED2-40B9-B0B8-7696FA280889}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F71217EC-9ED2-40B9-B0B8-7696FA280889}.Debug|x64.ActiveCfg = Debug|Any CPU
{F71217EC-9ED2-40B9-B0B8-7696FA280889}.Debug|x64.Build.0 = Debug|Any CPU
{F71217EC-9ED2-40B9-B0B8-7696FA280889}.Debug|x86.ActiveCfg = Debug|Any CPU
{F71217EC-9ED2-40B9-B0B8-7696FA280889}.Debug|x86.Build.0 = Debug|Any CPU
{F71217EC-9ED2-40B9-B0B8-7696FA280889}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F71217EC-9ED2-40B9-B0B8-7696FA280889}.Release|Any CPU.Build.0 = Release|Any CPU
{F71217EC-9ED2-40B9-B0B8-7696FA280889}.Release|x64.ActiveCfg = Release|Any CPU
{F71217EC-9ED2-40B9-B0B8-7696FA280889}.Release|x64.Build.0 = Release|Any CPU
{F71217EC-9ED2-40B9-B0B8-7696FA280889}.Release|x86.ActiveCfg = Release|Any CPU
{F71217EC-9ED2-40B9-B0B8-7696FA280889}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{B1463692-23C0-435B-A018-B6ED8F305E8D} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
EndGlobalSection
EndGlobal

5
scripts/package.ps1 Normal file
View File

@@ -0,0 +1,5 @@
#!/usr/bin/env sh
dotnet clean
dotnet build -c Release
dotnet pack

View File

@@ -1,3 +0,0 @@
#!/usr/bin/env sh
dotnet pack

View File

@@ -0,0 +1,30 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using System;
using System.ComponentModel;
using System.Globalization;
using System.Runtime.Serialization;
namespace Tribufu.ComponentModel
{
public class EnumMemberConverter<T> : EnumConverter
{
public EnumMemberConverter(Type type) : base(type) { }
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var type = typeof(T);
foreach (var field in type.GetFields())
{
if (Attribute.GetCustomAttribute(field, typeof(EnumMemberAttribute)) is EnumMemberAttribute attribute && value is string enumValue && attribute.Value == enumValue)
{
return field.GetValue(null);
}
}
return base.ConvertFrom(context, culture, value);
}
}
}

View File

@@ -0,0 +1 @@
# Tribufu ComponentModel

View File

@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PackageId>Tribufu.ComponentModel</PackageId>
<Description>Tribufu ComponentModel Extensions</Description>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
<PropertyGroup>
<AppDesignerFolder>Properties</AppDesignerFolder>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IsPublishable>false</IsPublishable>
<OutputType>Library</OutputType>
<TargetFrameworks>netstandard2.0;net45;net5.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="\" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,53 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Microsoft.Extensions.Configuration;
using System.IO;
using Tomlyn.Extensions.Configuration;
using Tribufu.Logging;
using Tribufu.Platform;
namespace Tribufu.Configuration
{
public static class ConfigurationLoader
{
public static IConfiguration Configuration { get; private set; }
public static IConfiguration Load(string[] fileNames)
{
var configDirectory = Paths.GetApplicationConfigDirectory();
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddEnvironmentVariables();
foreach (var fileName in fileNames)
{
var fullPath = Path.Combine(configDirectory, fileName);
if (!File.Exists(fullPath))
{
Logger.Debug($"Config file '{fullPath}' not found, skipping.");
continue;
}
var ext = Path.GetExtension(fullPath).ToLowerInvariant();
switch (ext)
{
case ".ini":
configurationBuilder.AddIniFile(fullPath, true, false);
break;
case ".json":
configurationBuilder.AddJsonFile(fullPath, true, false);
break;
case ".toml":
configurationBuilder.AddTomlFile(fullPath, true, false);
break;
default:
Logger.Warn($"Unsupported config file extension: {ext}");
break;
}
}
Configuration = configurationBuilder.Build();
return Configuration;
}
}
}

View File

@@ -0,0 +1 @@
# Tribufu Configuration

View File

@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PackageId>Tribufu.Configuration</PackageId>
<Description>Tribufu Configuration Extensions</Description>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
<PropertyGroup>
<AppDesignerFolder>Properties</AppDesignerFolder>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IsPublishable>false</IsPublishable>
<OutputType>Library</OutputType>
<TargetFrameworks>net6.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" />
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" />
<PackageReference Include="Microsoft.Extensions.Configuration" />
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="Tomlyn.Extensions.Configuration" />
<PackageReference Include="Tomlyn" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Tribufu.Logging\Tribufu.Logging.csproj" />
<ProjectReference Include="..\Tribufu.Platform\Tribufu.Platform.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,55 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Microsoft.Extensions.Configuration;
using System;
namespace Tribufu.Database
{
public class DatabaseConfiguration
{
public DatabaseDriver Driver { get; set; }
public string? Version { get; set; }
public string? Host { get; set; }
public string? Port { get; set; }
public string? User { get; set; }
public string? Password { get; set; }
public string? Schema { get; set; }
/// <summary>
/// Loads the <see cref="DatabaseConfiguration"/> from the "database" section or from root-level keys prefixed with "database_".
/// </summary>
/// <param name="configuration">The configuration source.</param>
/// <returns>The populated <see cref="DatabaseConfiguration"/> instance.</returns>
public static DatabaseConfiguration Load(IConfiguration configuration)
{
var section = configuration.GetSection("database");
var useRootFallback = !section.Exists();
string? GetConfig(string key) => useRootFallback ? configuration[$"database_{key}"] : section[key];
var driverString = GetConfig("driver") ?? throw new Exception("Missing database driver");
if (!Enum.TryParse<DatabaseDriver>(driverString, true, out var driver))
{
throw new Exception($"Unsupported database driver: {driverString}");
}
return new DatabaseConfiguration
{
Driver = driver,
Version = GetConfig("version"),
Host = GetConfig("host"),
Port = GetConfig("port"),
User = GetConfig("user"),
Password = GetConfig("password"),
Schema = GetConfig("schema")
};
}
}
}

View File

@@ -0,0 +1,12 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
namespace Tribufu.Database
{
public static class DatabaseConstants
{
public const uint DEFAULT_PAGINATION = 20;
public const uint MAX_PAGINATION = 100;
}
}

View File

@@ -0,0 +1,22 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
namespace Tribufu.Database
{
public enum DatabaseDriver : byte
{
MySql = 0,
Postgres = 1,
SqlServer = 2,
Oracle = 3,
Firebird = 4,
Sqlite = 5,
MongoDb = 6,
}
}

View File

@@ -0,0 +1 @@
# Tribufu Database

View File

@@ -0,0 +1,39 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Tribufu.Database.Repositories
{
public interface IRepository<T, K> where T : class
{
IList<T> GetAll();
Task<IList<T>> GetAllAsync();
IList<T> GetPage(uint page, uint limit);
Task<IList<T>> GetPageAsync(uint page, uint limit);
T? GetOne(K key);
Task<T?> GetOneAsync(K key);
T? Create(T entity);
Task<T?> CreateAsync(T entity);
T? Update(T entity);
Task<T?> UpdateAsync(T entity);
void Delete(K key);
Task DeleteAsync(K key);
void Delete(T entity);
Task DeleteAsync(T entity);
}
}

View File

@@ -0,0 +1,113 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Tribufu.Database.Repositories
{
public class Repository<C, T, K> : IRepository<T, K> where C : DbContext where T : class
{
protected readonly C _context;
protected readonly DbSet<T> _dbSet;
public Repository(C context)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
_dbSet = context.Set<T>();
}
public virtual IList<T> GetAll()
{
return [.. _dbSet];
}
public virtual async Task<IList<T>> GetAllAsync()
{
return await _dbSet.ToListAsync();
}
public virtual IList<T> GetPage(uint page, uint limit)
{
return _dbSet.Skip((int)((page < 1 ? 0 : page - 1) * limit)).Take((int)limit).ToList();
}
public virtual async Task<IList<T>> GetPageAsync(uint page, uint limit)
{
return await _dbSet.Skip((int)((page < 1 ? 0 : page - 1) * limit)).Take((int)limit).ToListAsync();
}
public virtual T? GetOne(K key)
{
return _dbSet.Find(key);
}
public virtual async Task<T?> GetOneAsync(K key)
{
return await _dbSet.FindAsync(key);
}
public virtual T? Create(T entity)
{
_dbSet.Add(entity);
var result = _context.SaveChanges();
return result > 0 ? entity : null;
}
public virtual async Task<T?> CreateAsync(T entity)
{
await _dbSet.AddAsync(entity);
var result = await _context.SaveChangesAsync();
return result > 0 ? entity : null;
}
public virtual T? Update(T entity)
{
_dbSet.Update(entity);
var result = _context.SaveChanges();
return result > 0 ? entity : null;
}
public virtual async Task<T?> UpdateAsync(T entity)
{
_dbSet.Update(entity);
var result = await _context.SaveChangesAsync();
return result > 0 ? entity : null;
}
public virtual void Delete(K key)
{
var entity = _dbSet.Find(key);
if (entity != null)
{
Delete(entity);
}
}
public virtual async Task DeleteAsync(K key)
{
var entity = await _dbSet.FindAsync(key);
if (entity != null)
{
await DeleteAsync(entity);
}
}
public virtual void Delete(T entity)
{
_dbSet.Remove(entity);
_context.SaveChanges();
}
public virtual async Task DeleteAsync(T entity)
{
_dbSet.Remove(entity);
await _context.SaveChangesAsync();
}
}
}

View File

@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PackageId>Tribufu.Database</PackageId>
<Description>Tribufu Database Extensions</Description>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
<PropertyGroup>
<AppDesignerFolder>Properties</AppDesignerFolder>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IsPublishable>false</IsPublishable>
<Nullable>enable</Nullable>
<OutputType>Library</OutputType>
<TargetFrameworks>net8.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Tribufu.Configuration\Tribufu.Configuration.csproj" />
<ProjectReference Include="..\Tribufu.Logging\Tribufu.Logging.csproj" />
<ProjectReference Include="..\Tribufu.Platform\Tribufu.Platform.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,9 +1,9 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: UNLICENSED
// SPDX-License-Identifier: MIT
using dotenv.net;
using Tribufu.Generated.Client;
using Tribufu.SafeCheck;
using Tribufu.Logging;
namespace Tribufu.Test
{
@@ -11,23 +11,23 @@ namespace Tribufu.Test
{
public static async Task Main(string[] args)
{
Logger.Initialize(LogLevel.Trace);
DotEnv.Load(new DotEnvOptions(ignoreExceptions: true, envFilePaths: [".env", "../../.env"]));
var apiKey = Environment.GetEnvironmentVariable("TRIBUFU_API_KEY");
var tribufu = new TribufuApi(apiKey ?? "");
Console.WriteLine(TribufuApi.GetVersion());
Logger.Debug(TribufuApi.GetUserAgent());
try
{
//var result = await tribufu.GetUserInfoAsync();
var safecheck = new TribufuSafeCheck(apiKey, "http://localhost:5100");
var result = await safecheck.CheckImageAsync("");
Console.WriteLine(result);
var result = await tribufu.GetUserInfoAsync();
Logger.Debug(result.ToString());
}
catch (ApiException e)
{
Console.WriteLine(e.Message);
Logger.Debug(e.Message);
}
}
}

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<IsPublishable>false</IsPublishable>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
@@ -9,7 +9,7 @@
<PackageReference Include="dotenv.net" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Tribufu.Logging\Tribufu.Logging.csproj" />
<ProjectReference Include="..\Tribufu\Tribufu.csproj" />
<ProjectReference Include="..\Tribufu.SafeCheck\Tribufu.SafeCheck.csproj" />
</ItemGroup>
</Project>

View File

@@ -1 +1 @@
# Tribufu
# Tribufu Generated

View File

@@ -8,7 +8,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<ImplicitUsings>enable</ImplicitUsings>
<IsPublishable>false</IsPublishable>
<Nullable>annotations</Nullable>
<OutputType>Library</OutputType>
<TargetFrameworks>net6.0</TargetFrameworks>

View File

@@ -0,0 +1,20 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
namespace Tribufu.Logging
{
public enum LogLevel : byte
{
Off = 0,
Error = 1,
Warn = 2,
Info = 3,
Debug = 4,
Trace = 5,
}
}

View File

@@ -0,0 +1,54 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using System;
namespace Tribufu.Logging
{
public static class Logger
{
private static LogLevel _level = LogLevel.Off;
public static void Initialize(LogLevel level = LogLevel.Off)
{
_level = level;
}
public static void Info(string message)
{
Log(LogLevel.Info, message, ConsoleColor.Green);
}
public static void Warn(string message)
{
Log(LogLevel.Warn, message, ConsoleColor.Yellow);
}
public static void Error(string message)
{
Log(LogLevel.Error, message, ConsoleColor.Red);
}
public static void Debug(string message)
{
Log(LogLevel.Debug, message, ConsoleColor.White);
}
public static void Trace(string message)
{
Log(LogLevel.Trace, message, ConsoleColor.DarkGray);
}
private static void Log(LogLevel level, string message, ConsoleColor color)
{
if (level <= _level)
{
var defaultColor = Console.ForegroundColor;
Console.ForegroundColor = color;
var timestamp = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss");
Console.WriteLine($"[{timestamp}] [{level.ToString().ToUpper()}]: {message}");
Console.ForegroundColor = defaultColor;
}
}
}
}

View File

@@ -0,0 +1 @@
# Tribufu Logging

View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PackageId>Tribufu.Logging</PackageId>
<Description>Tribufu Logging Extensions</Description>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
<PropertyGroup>
<AppDesignerFolder>Properties</AppDesignerFolder>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IsPublishable>false</IsPublishable>
<OutputType>Library</OutputType>
<TargetFrameworks>netstandard2.0;net45;net5.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="\" />
</ItemGroup>
<ItemGroup>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,62 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: UNLICENSED
using CppAst;
using CppAst.CodeGen.Common;
using CppAst.CodeGen.CSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Tribufu.Platform;
using Zio.FileSystems;
namespace Tribufu.Native.Generator
{
public class Program
{
public static void Main(string[] args)
{
var applicationDirectory = Paths.GetApplicationDirectory();
var includeDirectory = Path.Combine(applicationDirectory, "..", "sdk-rust", "include");
var tribufuIncludeDirectory = Path.Combine(includeDirectory, "tribufu");
List<string> headerDirectories = [includeDirectory, tribufuIncludeDirectory];
Console.WriteLine(includeDirectory);
var options = new CSharpConverterOptions()
{
DefaultNamespace = "Tribufu.Native",
DefaultClassLib = "NativeLibrary",
DefaultOutputFilePath = "./src/Tribufu.Native/NativeLibrary.cs",
GenerateEnumItemAsFields = false,
TypedefCodeGenKind = CppTypedefCodeGenKind.NoWrap,
DefaultDllImportNameAndArguments = "\"tribufu_sdk\"",
};
options.IncludeFolders.AddRange(headerDirectories);
var headerFiles = headerDirectories.SelectMany(dir => Directory.EnumerateFiles(dir, "*.h")).ToList();
var compilation = CSharpConverter.Convert(headerFiles, options);
if (compilation.HasErrors)
{
foreach (CppDiagnosticMessage message in compilation.Diagnostics.Messages)
{
if (message.Type == CppLogMessageType.Error)
{
Console.WriteLine(message);
}
}
return;
}
using var fileSystem = new PhysicalFileSystem();
using var subFileSystem = new SubFileSystem(fileSystem, fileSystem.ConvertPathFromInternal("."));
var writer = new CodeWriter(new CodeWriterOptions(subFileSystem));
compilation.DumpTo(writer);
}
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<IsPublishable>false</IsPublishable>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<UseAppHost>false</UseAppHost>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CppAst.CodeGen" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Tribufu.Platform\Tribufu.Platform.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IsPublishable>false</IsPublishable>
<Nullable>enable</Nullable>
<OutputType>Library</OutputType>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,122 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using System;
using System.IO;
using System.Runtime.InteropServices;
using Tribufu.Logging;
namespace Tribufu.Platform
{
/// <summary>
/// Provides standardized access to important directories, such as config, saved data, logs, and platform-specific binaries.
/// This is especially useful for abstracting file path logic across environments (development, production, etc).
/// </summary>
public static class Paths
{
/// <summary>
/// Gets the root base directory of the application.
/// </summary>
/// <remarks>
/// - In development, this resolves to the root of the repository (five levels above bin/Debug or bin/Release).
/// - In production, it resolves to two levels above the binary location.
/// - It uses case-insensitive checks and runtime heuristics to improve accuracy.
/// </remarks>
/// <returns>The absolute path to the base directory.</returns>
public static string GetApplicationDirectory()
{
try
{
string baseDirectory;
string defaultBaseDirectory = AppContext.BaseDirectory;
bool isDevelopment = defaultBaseDirectory.ToLowerInvariant().Contains("debug");
if (isDevelopment)
{
// Go 5 levels up to simulate project root
baseDirectory = Path.Combine(defaultBaseDirectory, "..", "..", "..", "..", "..");
}
else
{
baseDirectory = Path.Combine(defaultBaseDirectory, "..", "..");
}
return Path.GetFullPath(baseDirectory);
}
catch (Exception ex)
{
Logger.Warn($"(Paths) Failed to resolve base directory: {ex.Message}");
return AppContext.BaseDirectory;
}
}
/// <summary>
/// Gets the path to the platform-specific binary directory.
/// </summary>
/// <returns>
/// The absolute path to <c>bin/&lt;runtime-identifier&gt;</c> if available,
/// otherwise falls back to <c>bin/dotnet</c>.
/// </returns>
public static string GetApplicationBinDirectory()
{
var binDirectory = Path.Combine(GetApplicationDirectory(), "bin");
if (!string.IsNullOrEmpty(RuntimeInformation.RuntimeIdentifier))
{
binDirectory = Path.Combine(binDirectory, RuntimeInformation.RuntimeIdentifier);
}
else
{
binDirectory = Path.Combine(binDirectory, "dotnet");
}
return binDirectory;
}
/// <summary>
/// Gets the path to the configuration directory.
/// </summary>
/// <returns>The absolute path to the <c>config</c> directory.</returns>
public static string GetApplicationConfigDirectory()
{
return Path.Combine(GetApplicationDirectory(), "config");
}
/// <summary>
/// Gets the path to the assets directory.
/// </summary>
/// <returns>The absolute path to the <c>assets</c> directory.</returns>
public static string GetApplicationAssetsDirectory()
{
return Path.Combine(GetApplicationDirectory(), "assets");
}
/// <summary>
/// Gets the path to the saved data directory.
/// </summary>
/// <returns>The absolute path to the <c>saved</c> directory.</returns>
public static string GetApplicationSavedDirectory()
{
return Path.Combine(GetApplicationDirectory(), "saved");
}
/// <summary>
/// Gets the path to the cache directory inside <c>saved</c>.
/// </summary>
/// <returns>The absolute path to the <c>saved/cache</c> directory.</returns>
public static string GetApplicationCacheDirectory()
{
return Path.Combine(GetApplicationSavedDirectory(), "cache");
}
/// <summary>
/// Gets the path to the logs directory inside <c>saved</c>.
/// </summary>
/// <returns>The absolute path to the <c>saved/logs</c> directory.</returns>
public static string GetApplicationLogsDirectory()
{
return Path.Combine(GetApplicationSavedDirectory(), "logs");
}
}
}

View File

@@ -0,0 +1 @@
# Tribufu Runtime

View File

@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PackageId>Tribufu.Platform</PackageId>
<Description>Tribufu Runtime Extensions</Description>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
<PropertyGroup>
<AppDesignerFolder>Properties</AppDesignerFolder>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IsPublishable>false</IsPublishable>
<OutputType>Library</OutputType>
<TargetFrameworks>net5.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Tribufu.ComponentModel\Tribufu.ComponentModel.csproj" />
<ProjectReference Include="..\Tribufu.Logging\Tribufu.Logging.csproj" />
</ItemGroup>
</Project>

View File

@@ -1 +0,0 @@
# Tribufu

View File

@@ -1,25 +0,0 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
namespace Tribufu.SafeCheck
{
public class SafeCheckDetections
{
[JsonProperty("sexy")]
public double Sexy { get; set; }
[JsonProperty("porn")]
public double Porn { get; set; }
[JsonProperty("neutral")]
public double Neutral { get; set; }
[JsonProperty("hentai")]
public double Hentai { get; set; }
[JsonProperty("drawing")]
public double Drawing { get; set; }
}
}

View File

@@ -1,18 +0,0 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
namespace Tribufu.SafeCheck
{
public class SafeCheckRequest
{
[JsonProperty("image_url")]
public string ImageUrl { get; set; }
public SafeCheckRequest(string imageUrl)
{
ImageUrl = imageUrl;
}
}
}

View File

@@ -1,19 +0,0 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
namespace Tribufu.SafeCheck
{
public class SafecheckResponse
{
[JsonProperty("safe")]
public bool Safe { get; set; }
[JsonProperty("reason")]
public string? Reason { get; set; }
[JsonProperty("detections")]
public SafeCheckDetections? Detections { get; set; }
}
}

View File

@@ -1,27 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PackageId>Tribufu.SafeCheck</PackageId>
<Description>Tribufu SafeCheck</Description>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
<PropertyGroup>
<AppDesignerFolder>Properties</AppDesignerFolder>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<OutputType>Library</OutputType>
<TargetFrameworks>net6.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="RestSharp" />
<PackageReference Include="System.ComponentModel.Annotations" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Tribufu\Tribufu.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,56 +0,0 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
using RestSharp;
namespace Tribufu.SafeCheck
{
public sealed class TribufuSafeCheck
{
private readonly RestClient _client;
private readonly string? _apiKey;
public const string DefaultBaseUrl = "https://safecheck.tribufu.com";
public TribufuSafeCheck(string? apiKey = null, string baseUrl = DefaultBaseUrl)
{
var options = new RestClientOptions(baseUrl)
{
UserAgent = TribufuApi.GetUserAgent(),
};
_client = new RestClient(options);
_apiKey = apiKey;
}
public async Task<bool> CheckImageAsync(string imageUrl)
{
if (string.IsNullOrWhiteSpace(imageUrl))
{
throw new ArgumentException("Image URL cannot be null or empty.", nameof(imageUrl));
}
var request = new RestRequest("/image", Method.Post);
request.AddHeader("Content-Type", "application/json");
if (!string.IsNullOrEmpty(_apiKey))
{
request.AddHeader("Authorization", $"ApiKey {_apiKey}");
}
var requestBody = new SafeCheckRequest(imageUrl);
request.AddStringBody(JsonConvert.SerializeObject(requestBody), DataFormat.Json);
var response = await _client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
throw new Exception($"Request failed: {response.StatusCode} - {response.Content}");
}
var result = JsonConvert.DeserializeObject<SafecheckResponse>(response.Content!);
return result?.Safe ?? false;
}
}
}

View File

@@ -0,0 +1,46 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
using System;
using System.Globalization;
namespace Tribufu.Serialization
{
public class DecimalNullableStringConverter : JsonConverter<decimal?>
{
public override decimal? ReadJson(JsonReader reader, Type objectType, decimal? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
if (reader.TokenType == JsonToken.String || reader.TokenType == JsonToken.Integer)
{
string value = reader.Value?.ToString();
if (string.IsNullOrWhiteSpace(value))
{
return null;
}
return decimal.Parse(value);
}
throw new JsonSerializationException($"Unexpected token {reader.TokenType} when parsing decimal?.");
}
public override void WriteJson(JsonWriter writer, decimal? value, JsonSerializer serializer)
{
if (value.HasValue)
{
writer.WriteValue(value.Value.ToString(CultureInfo.InvariantCulture));
}
else
{
writer.WriteNull();
}
}
}
}

View File

@@ -0,0 +1,32 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
using System;
using System.Globalization;
namespace Tribufu.Serialization
{
public class DecimalStringConverter : JsonConverter<decimal>
{
public override decimal ReadJson(JsonReader reader, Type objectType, decimal existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.String && decimal.TryParse(reader.Value?.ToString(), out var result))
{
return result;
}
if (reader.TokenType == JsonToken.Integer)
{
return Convert.ToUInt64(reader.Value);
}
throw new JsonSerializationException($"Unexpected token {reader.TokenType} when parsing decimal.");
}
public override void WriteJson(JsonWriter writer, decimal value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString(CultureInfo.InvariantCulture));
}
}
}

View File

@@ -0,0 +1 @@
# Tribufu Serialization

View File

@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PackageId>Tribufu.Serialization</PackageId>
<Description>Tribufu Serialization Extensions</Description>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
<PropertyGroup>
<AppDesignerFolder>Properties</AppDesignerFolder>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IsPublishable>false</IsPublishable>
<OutputType>Library</OutputType>
<TargetFrameworks>netstandard2.0;net45;net5.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,45 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
using System;
namespace Tribufu.Serialization
{
public class ULongNullableStringConverter : JsonConverter<ulong?>
{
public override ulong? ReadJson(JsonReader reader, Type objectType, ulong? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
if (reader.TokenType == JsonToken.String || reader.TokenType == JsonToken.Integer)
{
string value = reader.Value?.ToString();
if (string.IsNullOrWhiteSpace(value))
{
return null;
}
return ulong.Parse(value);
}
throw new JsonSerializationException($"Unexpected token {reader.TokenType} when parsing ulong?.");
}
public override void WriteJson(JsonWriter writer, ulong? value, JsonSerializer serializer)
{
if (value.HasValue)
{
writer.WriteValue(value.Value.ToString());
}
else
{
writer.WriteNull();
}
}
}
}

View File

@@ -0,0 +1,31 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using Newtonsoft.Json;
using System;
namespace Tribufu.Serialization
{
public class ULongStringConverter : JsonConverter<ulong>
{
public override ulong ReadJson(JsonReader reader, Type objectType, ulong existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.String && ulong.TryParse(reader.Value?.ToString(), out var result))
{
return result;
}
if (reader.TokenType == JsonToken.Integer)
{
return Convert.ToUInt64(reader.Value);
}
throw new JsonSerializationException($"Unexpected token {reader.TokenType} when parsing ulong.");
}
public override void WriteJson(JsonWriter writer, ulong value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
}
}
}

View File

@@ -8,7 +8,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<ImplicitUsings>enable</ImplicitUsings>
<IsPublishable>false</IsPublishable>
<Nullable>annotations</Nullable>
<OutputType>Library</OutputType>
<TargetFrameworks>net6.0</TargetFrameworks>

View File

@@ -1,6 +1,7 @@
// Copyright (c) Tribufu. All Rights Reserved.
// SPDX-License-Identifier: MIT
using System;
using System.Net;
using System.Runtime.InteropServices;
using Tribufu.Generated.Api;
@@ -41,7 +42,7 @@ namespace Tribufu
/// Create a <see cref="TribufuApi"/> with the given API key.
/// </summary>
/// <remarks>
/// A API key gives you public read only access to the Tribufu API.
/// An API key gives you public read only access to the Tribufu API.
/// </remarks>
/// <param name="apiKey">The API key for authentication</param>
/// <returns><see cref="TribufuApi"/> instance configured with the API key</returns>