├── .gitignore ├── EFManager.ps1 ├── MiniMe.Aime ├── AimeHandler.cs ├── AimeServer.cs ├── AimeSession.cs ├── AimeUtility.cs ├── Data │ ├── AimeContext.cs │ ├── Migrations │ │ ├── 20200504004558_InitialCreate.Designer.cs │ │ ├── 20200504004558_InitialCreate.cs │ │ └── AimeContextModelSnapshot.cs │ └── Models │ │ └── AimeUser.cs ├── MiniMe.Aime.csproj └── Protocols │ ├── AimeHeader.cs │ ├── AimeRequest.cs │ ├── AimeResponse.cs │ ├── RegisterLevel.cs │ ├── Request │ ├── CampaignRequest.cs │ ├── FeliCaLookupRequest.cs │ ├── GoodbyeRequest.cs │ ├── HelloRequest.cs │ ├── LogRequest.cs │ ├── Lookup2Request.cs │ ├── LookupRequest.cs │ └── RegisterRequest.cs │ ├── Response │ ├── CampaignResponse.cs │ ├── FeliCaLookupResponse.cs │ ├── HelloResponse.cs │ ├── LogResponse.cs │ ├── Lookup2Response.cs │ ├── LookupResponse.cs │ └── RegisterResponse.cs │ └── Serialization │ ├── AimeDecoder.cs │ └── AimeEncoder.cs ├── MiniMe.AllNet ├── AllNetServer.cs ├── AllNetStartup.cs ├── Controllers │ └── ServletController.cs ├── MiniMe.AllNet.csproj └── Protocols │ ├── PowerOnRequest.cs │ └── PowerOnResponse.cs ├── MiniMe.Billing ├── BillingCryptoService.cs ├── BillingServer.cs ├── BillingStartup.cs ├── Controllers │ └── BillingController.cs ├── MiniMe.Billing.csproj └── Protocols │ ├── BillingRequest.cs │ └── BillingResponse.cs ├── MiniMe.Chunithm ├── ChunithmEvents.cs ├── ChunithmServer.cs ├── ChunithmStartup.cs ├── ChunithmUtility.cs ├── Comparers │ └── UserMusicEqualityComparer.cs ├── Controllers │ └── ServletController.cs ├── Data │ ├── ChunithmContext.cs │ ├── Migrations │ │ ├── 20200504030527_InitialCreate.Designer.cs │ │ ├── 20200504030527_InitialCreate.cs │ │ └── ChunithmContextModelSnapshot.cs │ └── Models │ │ ├── Common │ │ ├── IDbObject.cs │ │ └── IDbProfileObject.cs │ │ ├── UserActivity.cs │ │ ├── UserCharacter.cs │ │ ├── UserCourse.cs │ │ ├── UserDataEx.cs │ │ ├── UserDuelList.cs │ │ ├── UserGameOption.cs │ │ ├── UserGameOptionEx.cs │ │ ├── UserItem.cs │ │ ├── UserMap.cs │ │ ├── UserMusic.cs │ │ ├── UserPlayLog.cs │ │ └── UserProfile.cs ├── Middlewares │ └── QuirksMiddleware.cs ├── MiniMe.Chunithm.csproj └── Protocols │ ├── GameChargeItem.cs │ ├── GameEvent.cs │ ├── GameMessage.cs │ ├── GameRanking.cs │ ├── GameSale.cs │ ├── ILimitedPagination.cs │ ├── IPagination.cs │ ├── Request │ ├── GameLoginRequest.cs │ ├── GameLogoutRequest.cs │ ├── GetGameChargeRequest.cs │ ├── GetGameEventRequest.cs │ ├── GetGameIdlistRequest.cs │ ├── GetGameMessageRequest.cs │ ├── GetGameRankingRequest.cs │ ├── GetGameSaleRequest.cs │ ├── GetGameSettingRequest.cs │ ├── GetUserActivityRequest.cs │ ├── GetUserCharacterRequest.cs │ ├── GetUserChargeRequest.cs │ ├── GetUserCourseRequest.cs │ ├── GetUserDataExRequest.cs │ ├── GetUserDataRequest.cs │ ├── GetUserDuelRequest.cs │ ├── GetUserItemRequest.cs │ ├── GetUserMapRequest.cs │ ├── GetUserMusicRequest.cs │ ├── GetUserOptionExRequest.cs │ ├── GetUserOptionRequest.cs │ ├── GetUserPreviewRequest.cs │ ├── GetUserRecentRatingRequest.cs │ ├── GetUserRegionRequest.cs │ ├── UpsertClientBookkeepingRequest.cs │ ├── UpsertClientDevelopRequest.cs │ ├── UpsertClientErrorRequest.cs │ ├── UpsertClientSettingRequest.cs │ ├── UpsertClientTestModeRequest.cs │ └── UpsertUserAllRequest.cs │ ├── Response │ ├── GameLoginResponse.cs │ ├── GameLogoutResponse.cs │ ├── GetGameChargeResponse.cs │ ├── GetGameEventResponse.cs │ ├── GetGameIdlistResponse.cs │ ├── GetGameMessageResponse.cs │ ├── GetGameRankingResponse.cs │ ├── GetGameSaleResponse.cs │ ├── GetGameSettingResponse.cs │ ├── GetUserActivityResponse.cs │ ├── GetUserCharacterResponse.cs │ ├── GetUserChargeResponse.cs │ ├── GetUserCourseResponse.cs │ ├── GetUserDataExResponse.cs │ ├── GetUserDataResponse.cs │ ├── GetUserDuelResponse.cs │ ├── GetUserItemResponse.cs │ ├── GetUserMapResponse.cs │ ├── GetUserMusicResponse.cs │ ├── GetUserOptionExResponse.cs │ ├── GetUserOptionResponse.cs │ ├── GetUserPreviewResponse.cs │ ├── GetUserRecentRatingResponse.cs │ ├── GetUserRegionResponse.cs │ ├── UpsertClientBookkeepingResponse.cs │ ├── UpsertClientDevelopResponse.cs │ ├── UpsertClientErrorResponse.cs │ ├── UpsertClientSettingResponse.cs │ ├── UpsertClientTestmodeResponse.cs │ └── UpsertUserAllResponse.cs │ ├── UserActivity.cs │ ├── UserCharacter.cs │ ├── UserCourse.cs │ ├── UserDataEx.cs │ ├── UserDuelList.cs │ ├── UserGameOption.cs │ ├── UserGameOptionEx.cs │ ├── UserItem.cs │ ├── UserMap.cs │ ├── UserMusic.cs │ ├── UserPlayLog.cs │ ├── UserProfile.cs │ ├── UserRecentRating.cs │ └── UserRegion.cs ├── MiniMe.Core ├── AspNetCore │ ├── Extensions │ │ └── ConfigurationExtension.cs │ ├── Hosting │ │ ├── HostServerBase.cs │ │ └── HostStartupBase.cs │ ├── Middleswares │ │ ├── BodyBufferingMiddleware.cs │ │ └── MiddlewareBase.cs │ ├── Mvc │ │ └── Formatters │ │ │ ├── FormInputFormatter.cs │ │ │ └── FormOutputFormatter.cs │ ├── RequestDecompression │ │ ├── DeflateDecompressionProviderCollection.cs │ │ ├── IDecompressionProvider.cs │ │ ├── Providers │ │ │ ├── Base64DecompressionProvider.cs │ │ │ ├── DeflateDecompressionProvider.cs │ │ │ └── ZlibDecompressionProvider.cs │ │ ├── RequestDecompressionBuilderExtensions.cs │ │ ├── RequestDecompressionMiddleware.cs │ │ ├── RequestDecompressionOptions.cs │ │ ├── RequestDecompressionProvider.cs │ │ └── RequestDecompressionServicesExtensions.cs │ └── ResponseCompression │ │ └── ZlibCompressionProvider.cs ├── Extension │ ├── ILGeneratorExtension.cs │ ├── ReflectionExtension.cs │ └── SpanExtension.cs ├── IO │ └── ByteBuffer.cs ├── LoggerNameAttribute.cs ├── Mapper │ ├── DynamicAccessor.cs │ └── ObjectMapper.cs ├── MiniMe.Core.csproj ├── MiniMeEnvironment.cs ├── MiniMeService.cs ├── Models │ ├── IdzPorts.cs │ ├── MiniMePorts.cs │ └── PortSet.cs ├── Net │ ├── TcpServer.cs │ ├── TcpSession.cs │ └── Transform │ │ ├── CryptoPacketTransform.cs │ │ └── IPacketTransform.cs ├── ServerBase.cs ├── Services │ ├── IAimeService.cs │ └── ISwitchBoardService.cs ├── SwitchBoard.cs └── Utilities │ ├── ConsoleUtility.cs │ ├── HexUtility.cs │ ├── ProcessEnvironment.cs │ ├── ResourceManager.cs │ └── Validation.cs ├── MiniMe.sln ├── MiniMe.sln.DotSettings ├── MiniMe ├── MiniMe.csproj ├── Program.cs ├── Properties │ └── launchSettings.json └── appsettings.json ├── PubKeyInfra ├── billing.key ├── billing.pub ├── ca.crt ├── ca.key ├── ca.pem ├── server.key ├── server.pem └── server.pfx └── README.md /EFManager.ps1: -------------------------------------------------------------------------------- 1 | function Verify-Index { 2 | Param ( 3 | [string]$Index, 4 | [int]$Min, 5 | [int]$Max 6 | ) 7 | 8 | if ($Index -notmatch "^\d+$") { 9 | return $false 10 | } 11 | 12 | $Index = [int]$Index 13 | 14 | return $Min -le $Index -and $Index -le $Max 15 | } 16 | 17 | function Get-Projects { 18 | $result = New-Object System.Collections.Generic.List[System.Object] 19 | 20 | foreach ($projectDir in Get-ChildItem ./MiniMe.* -Directory) { 21 | $projectName = $projectDir.Name.Split(".", 2)[1] 22 | $dataDir = [IO.Path]::Combine($projectDir, 'Data') 23 | $contextFile = [IO.Path]::Combine($dataDir, "$($projectName)Context.cs") 24 | 25 | if (!(Test-Path $contextFile)) { 26 | continue 27 | } 28 | 29 | $result.Add([ordered]@{ 30 | Name = $projectName 31 | ProjectDirectory = $projectDir 32 | MigrationDirectory = [IO.Path]::Combine($dataDir, 'Migrations') 33 | }) 34 | } 35 | 36 | return $result 37 | } 38 | 39 | function Select-Project { 40 | while ($true) { 41 | Clear-Host 42 | Write-Host "================ Select Project ================" 43 | 44 | $projects = Get-Projects 45 | 46 | for ($i = 0; $i -lt $projects.Count; $i++) { 47 | Write-Host "$($i + 1). $($projects[$i].Name)" 48 | } 49 | 50 | Write-Host "$($projects.Count + 1). Exit" 51 | Write-Host 52 | 53 | $input = Read-Host "Project" 54 | 55 | if (!(Verify-Index $input -Min 1 -Max ($projects.Count + 1))) { 56 | continue 57 | } 58 | 59 | if ($input -eq 3) { 60 | return 61 | } else { 62 | return $projects[$input - 1] 63 | } 64 | 65 | pause 66 | } 67 | } 68 | 69 | function Delete-All-Migration($project) { 70 | do { 71 | $yn = (Read-Host "Delete all $($project.Name) migration data? (Y/N)").ToLower() 72 | } while ($yn -notin @('y','n')) 73 | 74 | if ($yn -eq 'y') { 75 | Remove-Item -Recurse -Force -ErrorAction Ignore $project.MigrationDirectory 76 | } 77 | } 78 | 79 | function Initialize-Migration($project) { 80 | if (Test-Path $project.MigrationDirectory) { 81 | Delete-All-Migration $project 82 | } 83 | 84 | dotnet ef migrations add InitialCreate -o $project.MigrationDirectory 85 | } 86 | 87 | function Create-Migration($project) { 88 | $name = Read-Host 'Input migration name' 89 | 90 | if ($name -match '^\w+$') { 91 | dotnet ef migrations add $Name -o ./Data/Migrations 92 | } 93 | else 94 | { 95 | Write-Error 'Invalid migration name.' 96 | } 97 | } 98 | 99 | function Run-Migration($project) { 100 | while ($true) { 101 | Clear-Host 102 | Write-Host "================ $($project.Name) EF Migration ================" 103 | Write-Host "1. Initialize migration" 104 | Write-Host "2. Creatre migration" 105 | Write-Host "3. Delete all migrations" 106 | Write-Host "4. Exit" 107 | Write-Host 108 | 109 | $input = Read-Host "Project" 110 | 111 | if (!(Verify-Index $input -Min 1 -Max 4)) { 112 | continue 113 | } 114 | 115 | Write-Host 116 | Set-Location $project.ProjectDirectory 117 | 118 | switch ($input) { 119 | 1 { 120 | Initialize-Migration $project 121 | } 122 | 2 { 123 | Create-Migration $project 124 | } 125 | 3 { 126 | Delete-All-Migration $project 127 | } 128 | 4 { 129 | return 130 | } 131 | } 132 | 133 | Write-Host 134 | Write-Host 'Done' 135 | 136 | pause 137 | return 138 | } 139 | } 140 | 141 | while ($true) { 142 | Set-Location $PSScriptRoot 143 | 144 | $selectedProject = Select-Project 145 | 146 | if ($selectedProject -eq $null) { 147 | return 148 | } 149 | 150 | Run-Migration $selectedProject 151 | } 152 | -------------------------------------------------------------------------------- /MiniMe.Aime/AimeHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using MiniMe.Aime.Data; 3 | using MiniMe.Aime.Data.Models; 4 | using MiniMe.Aime.Protocols; 5 | using MiniMe.Core.Utilities; 6 | using Serilog; 7 | 8 | namespace MiniMe.Aime 9 | { 10 | internal sealed class AimeHandler 11 | { 12 | private readonly AimeSession _session; 13 | private readonly AimeContext _context; 14 | private readonly ILogger _logger; 15 | 16 | public AimeHandler(AimeSession session, AimeContext context, ILogger logger) 17 | { 18 | _logger = logger; 19 | _session = session; 20 | _context = context; 21 | } 22 | 23 | public AimeResponse Dispatch(AimeRequest request) 24 | { 25 | switch (request) 26 | { 27 | case HelloRequest hello: 28 | return Hello(hello); 29 | 30 | case CampaignRequest campaign: 31 | return Campaign(campaign); 32 | 33 | case FeliCaLookupRequest feliCaLookup: 34 | return FeliCaLookup(feliCaLookup); 35 | 36 | case LookupRequest lookup: 37 | return Lookup(lookup); 38 | 39 | case Lookup2Request lookup2: 40 | return Lookup2(lookup2); 41 | 42 | case RegisterRequest register: 43 | return Register(register); 44 | 45 | case LogRequest log: 46 | return Log(log); 47 | 48 | case GoodbyeRequest goodbye: 49 | return Goodbye(goodbye); 50 | } 51 | 52 | throw new InvalidOperationException($"{request} handler not implemented"); 53 | } 54 | 55 | private TResponse Ok(TResponse response) where TResponse : AimeResponse 56 | { 57 | response.Status = 1; 58 | return response; 59 | } 60 | 61 | private HelloResponse Hello(HelloRequest request) 62 | { 63 | return Ok(new HelloResponse()); 64 | } 65 | 66 | private CampaignResponse Campaign(CampaignRequest request) 67 | { 68 | return Ok(new CampaignResponse()); 69 | } 70 | 71 | private FeliCaLookupResponse FeliCaLookup(FeliCaLookupRequest request) 72 | { 73 | string accessCode = HexUtility.HexToDecimalString(request.Idm).PadLeft(20, '0'); 74 | 75 | return Ok(new FeliCaLookupResponse 76 | { 77 | AccessCode = accessCode 78 | }); 79 | } 80 | 81 | private LookupResponse Lookup(LookupRequest request) 82 | { 83 | var user = _context.Find(u => u.AccessCode == request.AccessCode); 84 | 85 | return Ok(new LookupResponse 86 | { 87 | AimeId = user?.CardId, 88 | RegisterLevel = RegisterLevel.None 89 | }); 90 | } 91 | 92 | private Lookup2Response Lookup2(Lookup2Request request) 93 | { 94 | var user = _context.Find(u => u.AccessCode == request.AccessCode); 95 | 96 | return Ok(new Lookup2Response 97 | { 98 | AimeId = user?.CardId, 99 | RegisterLevel = RegisterLevel.None 100 | }); 101 | } 102 | 103 | private RegisterResponse Register(RegisterRequest request) 104 | { 105 | var user = new AimeUser 106 | { 107 | Id = Guid.NewGuid(), 108 | CardId = AimeUtility.GenerateCardId(), 109 | AccessCode = request.AccessCode, 110 | CreatedAt = DateTimeOffset.Now, 111 | AccessAt = DateTimeOffset.Now 112 | }; 113 | 114 | _context.Add(user); 115 | 116 | return Ok(new RegisterResponse 117 | { 118 | AimeId = user.CardId 119 | }); 120 | } 121 | 122 | private LogResponse Log(LogRequest request) 123 | { 124 | return Ok(new LogResponse()); 125 | } 126 | 127 | private AimeResponse Goodbye(GoodbyeRequest request) 128 | { 129 | return null; 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /MiniMe.Aime/AimeServer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using Microsoft.EntityFrameworkCore; 4 | using MiniMe.Aime.Data; 5 | using MiniMe.Core; 6 | using MiniMe.Core.Net; 7 | using MiniMe.Core.Repositories; 8 | 9 | namespace MiniMe.Aime 10 | { 11 | [LoggerName("\u001b[38;5;5mAime")] 12 | public sealed class AimeServer : TcpServer, IDisposable 13 | { 14 | private AimeContext _context; 15 | 16 | public AimeServer(IPEndPoint endPoint) : base(endPoint) 17 | { 18 | _context = new AimeContext(); 19 | _context.Database.Migrate(); 20 | 21 | MiniMeService.Add(_context); 22 | } 23 | 24 | protected override AimeSession CreateSession() 25 | { 26 | return new AimeSession(_context, Logger); 27 | } 28 | 29 | public void Dispose() 30 | { 31 | MiniMeService.Remove(); 32 | 33 | _context?.Dispose(); 34 | _context = null; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /MiniMe.Aime/AimeSession.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Security.Cryptography; 4 | using MiniMe.Aime.Data; 5 | using MiniMe.Aime.Protocols; 6 | using MiniMe.Aime.Protocols.Serialization; 7 | using MiniMe.Core.Extension; 8 | using MiniMe.Core.IO; 9 | using MiniMe.Core.Net; 10 | using MiniMe.Core.Net.Transform; 11 | using MiniMe.Core.Utilities; 12 | using Serilog; 13 | 14 | namespace MiniMe.Aime 15 | { 16 | public sealed class AimeSession : TcpSession 17 | { 18 | private readonly AimeHandler _handler; 19 | private readonly ILogger _logger; 20 | 21 | private ByteBuffer _incompleteFrame; 22 | 23 | internal AimeSession(AimeContext context, ILogger logger) 24 | { 25 | _logger = logger; 26 | _handler = new AimeHandler(this, context, logger); 27 | 28 | AddReceiveTransform(new CryptoPacketTransform(_decryptor, true)); 29 | AddSendTransform(new CryptoPacketTransform(_encryptor)); 30 | } 31 | 32 | protected override void OnBadPacketReceived(ReadOnlySpan packet, DateTime recivedTime, Exception exception) 33 | { 34 | const string message = "{id} Bad packet received.\nPacket({length}): {packet}"; 35 | 36 | byte[] packetBin = packet.ToArray(); 37 | var packetStr = string.Join(", ", packetBin); 38 | 39 | if (exception != null) 40 | { 41 | _logger?.Warning(exception, message, Id, packet.Length, packetStr); 42 | } 43 | else 44 | { 45 | _logger?.Warning(message, Id, packet.Length, packetStr); 46 | } 47 | } 48 | 49 | protected override void OnPacketReceived(ReadOnlySpan packet, DateTime reciveTime) 50 | { 51 | while (true) 52 | { 53 | if (_incompleteFrame != null) 54 | { 55 | int incompleteLength = _incompleteFrame.Length; 56 | 57 | _incompleteFrame.Resize(incompleteLength + packet.Length); 58 | packet.CopyTo(_incompleteFrame.Data.AsSpan(incompleteLength)); 59 | 60 | packet = _incompleteFrame.Data; 61 | _incompleteFrame = null; 62 | } 63 | 64 | if (packet.Length < Marshal.SizeOf()) 65 | { 66 | _incompleteFrame = new ByteBuffer(packet.ToArray()); 67 | return; 68 | } 69 | 70 | var header = packet.Read(); 71 | 72 | if (header.Id != AimeHeader.MagicId) 73 | { 74 | throw new InvalidOperationException($"Invalid magic 0x{header.Id:X}({header.Id})"); 75 | } 76 | 77 | if (packet.Length < header.FrameLength) 78 | { 79 | _incompleteFrame = new ByteBuffer(packet.ToArray()); 80 | return; 81 | } 82 | 83 | OnFrameReceived(packet.Slice(0, header.FrameLength), reciveTime); 84 | 85 | if (packet.Length > header.FrameLength) 86 | { 87 | packet = packet.Slice(header.FrameLength); 88 | continue; 89 | } 90 | 91 | break; 92 | } 93 | } 94 | 95 | private void OnFrameReceived(ReadOnlySpan packet, DateTime reciveTime) 96 | { 97 | var request = AimeDecoder.Decode(ref packet); 98 | 99 | _logger?.Information("{id} Request {@request} received.", Id, request); 100 | 101 | var response = _handler.Dispatch(request); 102 | 103 | if (response != null) 104 | { 105 | Send(AimeEncoder.Encode(response)); 106 | } 107 | 108 | var duration = DateTime.Now - reciveTime; 109 | _logger?.Information("{id} Response {@response} in {ms:0.0000}ms", Id, response, duration.TotalMilliseconds); 110 | } 111 | 112 | #region Crypto 113 | private static readonly ICryptoTransform _decryptor; 114 | private static readonly ICryptoTransform _encryptor; 115 | 116 | static AimeSession() 117 | { 118 | var aes = new RijndaelManaged 119 | { 120 | BlockSize = 128, 121 | Key = HexUtility.HexToBytes("436f7079726967687428432953454741"), 122 | Mode = CipherMode.ECB, 123 | Padding = PaddingMode.Zeros 124 | }; 125 | 126 | _decryptor = aes.CreateDecryptor(); 127 | _encryptor = aes.CreateEncryptor(); 128 | } 129 | #endregion 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /MiniMe.Aime/AimeUtility.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Cryptography; 3 | using MiniMe.Core.Extension; 4 | 5 | namespace MiniMe.Aime 6 | { 7 | internal static class AimeUtility 8 | { 9 | private static RNGCryptoServiceProvider _rngCsp; 10 | 11 | public static int GenerateCardId() 12 | { 13 | _rngCsp ??= new RNGCryptoServiceProvider(); 14 | 15 | Span buffer = stackalloc byte[4]; 16 | _rngCsp.GetBytes(buffer); 17 | 18 | return Math.Abs(buffer.Read()); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /MiniMe.Aime/Data/AimeContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using Microsoft.EntityFrameworkCore; 6 | using MiniMe.Aime.Data.Models; 7 | using MiniMe.Core; 8 | using MiniMe.Core.Repositories; 9 | 10 | namespace MiniMe.Aime.Data 11 | { 12 | public sealed class AimeContext : DbContext, IAimeService 13 | { 14 | public DbSet AimeUsers { get; set; } 15 | 16 | protected override void OnConfiguring(DbContextOptionsBuilder options) 17 | { 18 | options.UseSqlite($"Data Source={MiniMeEnvironment.GetDataFile("aime.db")}"); 19 | } 20 | 21 | public void Add(AimeUser user) 22 | { 23 | AimeUsers.Add(user); 24 | SaveChanges(); 25 | } 26 | 27 | public AimeUser Find(Expression> expression) 28 | { 29 | var user = AimeUsers.FirstOrDefault(expression); 30 | 31 | if (user != null) 32 | { 33 | user.AccessAt = DateTimeOffset.Now; 34 | SaveChanges(); 35 | } 36 | 37 | return user; 38 | } 39 | 40 | #region IAimeService 41 | private readonly ConcurrentDictionary _idCache = new ConcurrentDictionary(); 42 | 43 | Guid? IAimeService.FindIdByCardId(int cardId) 44 | { 45 | if (!_idCache.TryGetValue(cardId, out Guid? aimeId)) 46 | { 47 | aimeId = AimeUsers 48 | .AsNoTracking() 49 | .FirstOrDefault(u => u.CardId == cardId)?.Id; 50 | 51 | _idCache[cardId] = aimeId; 52 | } 53 | 54 | return aimeId; 55 | } 56 | #endregion 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /MiniMe.Aime/Data/Migrations/20200504004558_InitialCreate.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Migrations; 6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 7 | using MiniMe.Aime.Data; 8 | 9 | namespace MiniMe.Aime.Data.Migrations 10 | { 11 | [DbContext(typeof(AimeContext))] 12 | [Migration("20200504004558_InitialCreate")] 13 | partial class InitialCreate 14 | { 15 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 16 | { 17 | #pragma warning disable 612, 618 18 | modelBuilder 19 | .HasAnnotation("ProductVersion", "3.1.3"); 20 | 21 | modelBuilder.Entity("MiniMe.Aime.Data.Models.AimeUser", b => 22 | { 23 | b.Property("Id") 24 | .ValueGeneratedOnAdd() 25 | .HasColumnType("TEXT"); 26 | 27 | b.Property("AccessAt") 28 | .HasColumnType("TEXT"); 29 | 30 | b.Property("AccessCode") 31 | .IsRequired() 32 | .HasColumnType("TEXT"); 33 | 34 | b.Property("CardId") 35 | .HasColumnType("INTEGER"); 36 | 37 | b.Property("CreatedAt") 38 | .HasColumnType("TEXT"); 39 | 40 | b.HasKey("Id"); 41 | 42 | b.ToTable("AimeUsers"); 43 | }); 44 | #pragma warning restore 612, 618 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /MiniMe.Aime/Data/Migrations/20200504004558_InitialCreate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | namespace MiniMe.Aime.Data.Migrations 5 | { 6 | public partial class InitialCreate : Migration 7 | { 8 | protected override void Up(MigrationBuilder migrationBuilder) 9 | { 10 | migrationBuilder.CreateTable( 11 | name: "AimeUsers", 12 | columns: table => new 13 | { 14 | Id = table.Column(nullable: false), 15 | CardId = table.Column(nullable: false), 16 | AccessCode = table.Column(nullable: false), 17 | CreatedAt = table.Column(nullable: false), 18 | AccessAt = table.Column(nullable: false) 19 | }, 20 | constraints: table => 21 | { 22 | table.PrimaryKey("PK_AimeUsers", x => x.Id); 23 | }); 24 | } 25 | 26 | protected override void Down(MigrationBuilder migrationBuilder) 27 | { 28 | migrationBuilder.DropTable( 29 | name: "AimeUsers"); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /MiniMe.Aime/Data/Migrations/AimeContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 6 | using MiniMe.Aime.Data; 7 | 8 | namespace MiniMe.Aime.Data.Migrations 9 | { 10 | [DbContext(typeof(AimeContext))] 11 | partial class AimeContextModelSnapshot : ModelSnapshot 12 | { 13 | protected override void BuildModel(ModelBuilder modelBuilder) 14 | { 15 | #pragma warning disable 612, 618 16 | modelBuilder 17 | .HasAnnotation("ProductVersion", "3.1.3"); 18 | 19 | modelBuilder.Entity("MiniMe.Aime.Data.Models.AimeUser", b => 20 | { 21 | b.Property("Id") 22 | .ValueGeneratedOnAdd() 23 | .HasColumnType("TEXT"); 24 | 25 | b.Property("AccessAt") 26 | .HasColumnType("TEXT"); 27 | 28 | b.Property("AccessCode") 29 | .IsRequired() 30 | .HasColumnType("TEXT"); 31 | 32 | b.Property("CardId") 33 | .HasColumnType("INTEGER"); 34 | 35 | b.Property("CreatedAt") 36 | .HasColumnType("TEXT"); 37 | 38 | b.HasKey("Id"); 39 | 40 | b.ToTable("AimeUsers"); 41 | }); 42 | #pragma warning restore 612, 618 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /MiniMe.Aime/Data/Models/AimeUser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace MiniMe.Aime.Data.Models 5 | { 6 | public sealed class AimeUser 7 | { 8 | [Key] 9 | [Required] 10 | public Guid Id { get; set; } 11 | 12 | [Required] 13 | public int CardId { get; set; } 14 | 15 | [Required] 16 | public string AccessCode { get; set; } 17 | 18 | public DateTimeOffset CreatedAt { get; set; } 19 | 20 | public DateTimeOffset AccessAt { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /MiniMe.Aime/MiniMe.Aime.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | all 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/AimeHeader.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace MiniMe.Aime.Protocols 4 | { 5 | [StructLayout(LayoutKind.Sequential)] 6 | internal struct AimeHeader 7 | { 8 | public const ushort MagicId = 0xa13e; 9 | public const ushort MagicId2 = 0x3087; 10 | 11 | public ushort Id { get; set; } // Magic? 12 | 13 | public ushort Id2 { get; set; } // ??? 14 | 15 | public ushort OpCode { get; set; } 16 | 17 | public ushort FrameLength { get; set; } 18 | 19 | public static AimeHeader Create(ushort opCode, ushort size) 20 | { 21 | return new AimeHeader 22 | { 23 | Id = MagicId, 24 | Id2 = MagicId2, 25 | OpCode = opCode, 26 | FrameLength = size 27 | }; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/AimeRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Aime.Protocols 2 | { 3 | internal abstract class AimeRequest 4 | { 5 | public string GameId { get; set; } 6 | 7 | public string KeyChipId { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/AimeResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Aime.Protocols 2 | { 3 | internal abstract class AimeResponse 4 | { 5 | public ushort Status { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/RegisterLevel.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Aime.Protocols 2 | { 3 | internal enum RegisterLevel 4 | { 5 | None, 6 | Portal, 7 | SegaId 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/Request/CampaignRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Aime.Protocols 2 | { 3 | internal sealed class CampaignRequest : AimeRequest 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/Request/FeliCaLookupRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Aime.Protocols 2 | { 3 | internal sealed class FeliCaLookupRequest : AimeRequest 4 | { 5 | public string Idm { get; set; } 6 | 7 | public string Pmm { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/Request/GoodbyeRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Aime.Protocols 2 | { 3 | internal sealed class GoodbyeRequest : AimeRequest 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/Request/HelloRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Aime.Protocols 2 | { 3 | internal sealed class HelloRequest : AimeRequest 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/Request/LogRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Aime.Protocols 2 | { 3 | internal sealed class LogRequest : AimeRequest 4 | { 5 | public uint Field20 { get; set; } 6 | 7 | public uint Field24 { get; set; } 8 | 9 | public uint Field28 { get; set; } 10 | 11 | public uint Field2C { get; set; } 12 | 13 | public uint Field30 { get; set; } 14 | 15 | public uint Field34 { get; set; } 16 | 17 | public uint Field38 { get; set; } 18 | 19 | public uint Field3C { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/Request/Lookup2Request.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Aime.Protocols 2 | { 3 | internal sealed class Lookup2Request : AimeRequest 4 | { 5 | public string AccessCode { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/Request/LookupRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Aime.Protocols 2 | { 3 | internal sealed class LookupRequest : AimeRequest 4 | { 5 | public string AccessCode { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/Request/RegisterRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Aime.Protocols 2 | { 3 | internal sealed class RegisterRequest : AimeRequest 4 | { 5 | public string AccessCode { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/Response/CampaignResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Aime.Protocols 2 | { 3 | internal sealed class CampaignResponse : AimeResponse 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/Response/FeliCaLookupResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Aime.Protocols 2 | { 3 | internal sealed class FeliCaLookupResponse : AimeResponse 4 | { 5 | public string AccessCode { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/Response/HelloResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Aime.Protocols 2 | { 3 | internal sealed class HelloResponse : AimeResponse 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/Response/LogResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Aime.Protocols 2 | { 3 | internal sealed class LogResponse : AimeResponse 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/Response/Lookup2Response.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Aime.Protocols 2 | { 3 | internal sealed class Lookup2Response : AimeResponse 4 | { 5 | public int? AimeId { get; set; } 6 | 7 | public RegisterLevel RegisterLevel { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/Response/LookupResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Aime.Protocols 2 | { 3 | internal sealed class LookupResponse : AimeResponse 4 | { 5 | public int? AimeId { get; set; } 6 | 7 | public RegisterLevel RegisterLevel { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/Response/RegisterResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Aime.Protocols 2 | { 3 | internal sealed class RegisterResponse : AimeResponse 4 | { 5 | public int? AimeId { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/Serialization/AimeDecoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using MiniMe.Core.Extension; 5 | using MiniMe.Core.Utilities; 6 | 7 | namespace MiniMe.Aime.Protocols.Serialization 8 | { 9 | internal static class AimeDecoder 10 | { 11 | private delegate AimeRequest DecodeCallback(ref ReadOnlySpan packet); 12 | 13 | private static readonly Dictionary _readers = 14 | new Dictionary 15 | { 16 | [0x0001] = DecodeFeliCaLookupRequest, 17 | [0x0004] = DecodeLookupRequest, 18 | [0x0005] = DecodeRegisterRequest, 19 | [0x0009] = DecodeLogRequest, 20 | [0x000b] = DecodeCampaignRequest, 21 | [0x000d] = DecodeRegisterRequest, 22 | [0x000f] = DecodeLookupRequest2, 23 | [0x0064] = DecodeHelloRequest, 24 | [0x0066] = DecodeGoodbyeRequest 25 | }; 26 | 27 | public static AimeRequest Decode(ref ReadOnlySpan packet) 28 | { 29 | var header = packet.Read(); 30 | 31 | if (_readers.TryGetValue(header.OpCode, out var decoder)) 32 | { 33 | return decoder(ref packet); 34 | } 35 | 36 | throw new InvalidOperationException($"Unknown operation code 0x{header.OpCode:X}({header.OpCode})"); 37 | } 38 | 39 | #region Decoders 40 | private static void DecodeMetadata(AimeRequest request, ref ReadOnlySpan packet) 41 | { 42 | request.GameId = Encoding.ASCII.GetString(packet.Slice(10, 4)); 43 | request.KeyChipId = Encoding.ASCII.GetString(packet.Slice(20, 11)); 44 | } 45 | 46 | private static AimeRequest DecodeFeliCaLookupRequest(ref ReadOnlySpan packet) 47 | { 48 | var request = new FeliCaLookupRequest(); 49 | 50 | DecodeMetadata(request, ref packet); 51 | request.Idm = HexUtility.BytesToHex(packet.Slice(32, 8)); 52 | request.Pmm = HexUtility.BytesToHex(packet.Slice(40, 8)); 53 | 54 | return request; 55 | } 56 | 57 | private static AimeRequest DecodeLookupRequest(ref ReadOnlySpan packet) 58 | { 59 | var request = new Lookup2Request(); 60 | 61 | DecodeMetadata(request, ref packet); 62 | request.AccessCode = HexUtility.BytesToHex(packet.Slice(32, 10)); 63 | 64 | return request; 65 | } 66 | 67 | private static AimeRequest DecodeLogRequest(ref ReadOnlySpan packet) 68 | { 69 | var request = new LogRequest(); 70 | 71 | DecodeMetadata(request, ref packet); 72 | request.Field20 = packet.Read(0x20); 73 | request.Field24 = packet.Read(0x24); 74 | request.Field28 = packet.Read(0x28); 75 | request.Field2C = packet.Read(0x2C); 76 | request.Field30 = packet.Read(0x30); 77 | request.Field34 = packet.Read(0x34); 78 | request.Field38 = packet.Read(0x38); 79 | request.Field3C = packet.Read(0x3C); 80 | 81 | return request; 82 | } 83 | 84 | private static AimeRequest DecodeCampaignRequest(ref ReadOnlySpan packet) 85 | { 86 | var request = new CampaignRequest(); 87 | 88 | DecodeMetadata(request, ref packet); 89 | 90 | return request; 91 | } 92 | 93 | private static AimeRequest DecodeRegisterRequest(ref ReadOnlySpan packet) 94 | { 95 | var request = new RegisterRequest(); 96 | 97 | DecodeMetadata(request, ref packet); 98 | request.AccessCode = HexUtility.BytesToHex(packet.Slice(32, 10)); 99 | 100 | return request; 101 | } 102 | 103 | private static AimeRequest DecodeLookupRequest2(ref ReadOnlySpan packet) 104 | { 105 | var request = new Lookup2Request(); 106 | 107 | DecodeMetadata(request, ref packet); 108 | request.AccessCode = HexUtility.BytesToHex(packet.Slice(32, 10)); 109 | 110 | return request; 111 | } 112 | 113 | private static AimeRequest DecodeHelloRequest(ref ReadOnlySpan packet) 114 | { 115 | var request = new HelloRequest(); 116 | 117 | DecodeMetadata(request, ref packet); 118 | 119 | return request; 120 | } 121 | 122 | private static AimeRequest DecodeGoodbyeRequest(ref ReadOnlySpan packet) 123 | { 124 | return new GoodbyeRequest(); 125 | } 126 | #endregion 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /MiniMe.Aime/Protocols/Serialization/AimeEncoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using MiniMe.Core.Extension; 4 | using MiniMe.Core.Utilities; 5 | 6 | namespace MiniMe.Aime.Protocols.Serialization 7 | { 8 | internal static class AimeEncoder 9 | { 10 | private static readonly Dictionary _headers = 11 | new Dictionary 12 | { 13 | [typeof(FeliCaLookupResponse)] = AimeHeader.Create(0x0003, 48), 14 | [typeof(HelloResponse)] = AimeHeader.Create(0x0065, 20), 15 | [typeof(CampaignResponse)] = AimeHeader.Create(0x000c, 512), 16 | [typeof(LookupResponse)] = AimeHeader.Create(0x0006, 304), 17 | [typeof(Lookup2Response)] = AimeHeader.Create(0x0010, 304), 18 | [typeof(RegisterResponse)] = AimeHeader.Create(0x0006, 48), 19 | [typeof(LogResponse)] = AimeHeader.Create(0x000a, 32), 20 | }; 21 | 22 | public static ReadOnlySpan Encode(AimeResponse response) 23 | { 24 | if (!_headers.TryGetValue(response.GetType(), out var header)) 25 | { 26 | throw new NotSupportedException("Not supported response type"); 27 | } 28 | 29 | Span packet = new byte[header.FrameLength]; 30 | packet.Write(header); 31 | packet.Write(response.Status, 8); 32 | 33 | switch (response) 34 | { 35 | case FeliCaLookupResponse fcLookup: 36 | packet.Write(HexUtility.HexToBytes(fcLookup.AccessCode), 36); 37 | break; 38 | 39 | case LookupResponse lookup: 40 | packet.Write(lookup.AimeId ?? -1, 32); 41 | packet.Write((byte)lookup.RegisterLevel, 36); 42 | break; 43 | 44 | case Lookup2Response lookup2: 45 | packet.Write(lookup2.AimeId ?? -1, 32); 46 | packet.Write((byte)lookup2.RegisterLevel, 36); 47 | break; 48 | 49 | case RegisterResponse register: 50 | packet.Write(register.AimeId ?? -1, 32); 51 | break; 52 | } 53 | 54 | return packet; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /MiniMe.AllNet/AllNetServer.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using Microsoft.AspNetCore.Hosting; 3 | using MiniMe.Core; 4 | using MiniMe.Core.AspNetCore.Hosting; 5 | 6 | namespace MiniMe.AllNet 7 | { 8 | [LoggerName("\u001b[38;5;3mAllNet")] 9 | public sealed class AllNetServer : HostServerBase 10 | { 11 | public AllNetServer(IPEndPoint endPoint) : base(endPoint) 12 | { 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MiniMe.AllNet/AllNetStartup.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Microsoft.AspNetCore.Builder; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using MiniMe.Core; 6 | using MiniMe.Core.AspNetCore.Hosting; 7 | using MiniMe.Core.AspNetCore.Mvc.Formatters; 8 | using MiniMe.Core.AspNetCore.RequestDecompression; 9 | using MiniMe.Core.Repositories; 10 | 11 | namespace MiniMe.AllNet 12 | { 13 | public class AllNetStartup : HostStartupBase 14 | { 15 | public override void Configure(IApplicationBuilder app) 16 | { 17 | app.UseRequestDecompression(); 18 | base.Configure(app); 19 | } 20 | 21 | public override void ConfigureServices(IServiceCollection services) 22 | { 23 | services.AddSingleton(MiniMeService.Get()); 24 | 25 | services.AddRequestDecompression(o => 26 | { 27 | o.Providers.Add(); 28 | o.Providers.Add(); 29 | }); 30 | 31 | base.ConfigureServices(services); 32 | } 33 | 34 | protected override void ConfigureControllers(MvcOptions options) 35 | { 36 | options.InputFormatters.Insert(0, new FormInputFormatter()); 37 | 38 | options.OutputFormatters.Insert(0, new FormOutputFormatter 39 | { 40 | SupportedEncodings = { Encoding.GetEncoding(932) } 41 | }); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /MiniMe.AllNet/Controllers/ServletController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Mvc; 3 | using MiniMe.AllNet.Protocols; 4 | using MiniMe.Core; 5 | using MiniMe.Core.Repositories; 6 | using MiniMe.Core.Utilities; 7 | 8 | namespace MiniMe.AllNet.Controllers 9 | { 10 | [ApiController] 11 | [Route("/sys/servlet")] 12 | public class ServletController : ControllerBase 13 | { 14 | private readonly ISwitchBoardService _switchBoard; 15 | 16 | public ServletController(ISwitchBoardService switchBoard) 17 | { 18 | _switchBoard = switchBoard ?? throw new ArgumentException(nameof(switchBoard)); 19 | } 20 | 21 | [HttpPost("PowerOn")] 22 | [Consumes("application/x-www-form-urlencoded")] 23 | public PowerOnResponse PowerOnFromForm(PowerOnRequest request) 24 | { 25 | return PowerOn(request); 26 | } 27 | 28 | [HttpPost("PowerOn")] 29 | public PowerOnResponse PowerOn([FromBody] PowerOnRequest request) 30 | { 31 | int hourDelta = int.Parse(ProcessEnvironment.GetEnvironmentVariable("HOUR_DELTA") ?? "0"); 32 | var now = DateTime.UtcNow.AddHours(-hourDelta); 33 | 34 | return new PowerOnResponse 35 | { 36 | Stat = 1, 37 | Uri = _switchBoard.GetStartupUri(request.GameId) ?? string.Empty, 38 | Host = _switchBoard.GetStartupHost(request.GameId) ?? string.Empty, 39 | PlaceId = "123", 40 | Name = ProcessEnvironment.GetEnvironmentVariable("SHOW_NAME") ?? string.Empty, 41 | Nickname = ProcessEnvironment.GetEnvironmentVariable("SHOW_NAME") ?? string.Empty, 42 | Region0 = "1", 43 | RegionName0 = "W", 44 | RegionName1 = "X", 45 | RegionName2 = "Y", 46 | RegionName3 = "Z", 47 | Country = ProcessEnvironment.GetEnvironmentVariable("SHOW_REGION") ?? "JPN", 48 | AllNetId = "456", 49 | ClientTimezone = "+0900", 50 | UtcTime = $"{now:s}Z", 51 | Setting = string.Empty, 52 | ResVersion = "3", 53 | Token = request.Token 54 | }; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /MiniMe.AllNet/MiniMe.AllNet.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /MiniMe.AllNet/Protocols/PowerOnRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | 4 | namespace MiniMe.AllNet.Protocols 5 | { 6 | public class PowerOnRequest 7 | { 8 | [JsonProperty("game_id")] 9 | public string GameId { get; set; } 10 | 11 | [JsonProperty("ver")] 12 | public Version Version { get; set; } 13 | 14 | [JsonProperty("serial")] 15 | public string Serial { get; set; } 16 | 17 | [JsonProperty("ip")] 18 | public string Ip { get; set; } 19 | 20 | [JsonProperty("firm_ver")] 21 | public string FirmVersion { get; set; } 22 | 23 | [JsonProperty("boot_ver")] 24 | public string BootVersion { get; set; } 25 | 26 | [JsonProperty("encode")] 27 | public string Encode { get; set; } 28 | 29 | [JsonProperty("format_ver")] 30 | public string FormatVersion { get; set; } 31 | 32 | [JsonProperty("hops")] 33 | public string Hops { get; set; } 34 | 35 | [JsonProperty("token")] 36 | public string Token { get; set; } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /MiniMe.AllNet/Protocols/PowerOnResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace MiniMe.AllNet.Protocols 4 | { 5 | public class PowerOnResponse 6 | { 7 | [JsonProperty("stat")] 8 | public int Stat { get; set; } 9 | 10 | [JsonProperty("uri")] 11 | public string Uri { get; set; } 12 | 13 | [JsonProperty("host")] 14 | public string Host { get; set; } 15 | 16 | [JsonProperty("place_id")] 17 | public string PlaceId { get; set; } 18 | 19 | [JsonProperty("name")] 20 | public string Name { get; set; } 21 | 22 | [JsonProperty("nickname")] 23 | public string Nickname { get; set; } 24 | 25 | [JsonProperty("region0")] 26 | public string Region0 { get; set; } 27 | 28 | [JsonProperty("region_name0")] 29 | public string RegionName0 { get; set; } 30 | 31 | [JsonProperty("region_name1")] 32 | public string RegionName1 { get; set; } 33 | 34 | [JsonProperty("region_name2")] 35 | public string RegionName2 { get; set; } 36 | 37 | [JsonProperty("region_name3")] 38 | public string RegionName3 { get; set; } 39 | 40 | [JsonProperty("country")] 41 | public string Country { get; set; } 42 | 43 | [JsonProperty("allnet_id")] 44 | public string AllNetId { get; set; } 45 | 46 | [JsonProperty("client_timezone")] 47 | public string ClientTimezone { get; set; } 48 | 49 | [JsonProperty("utc_time")] 50 | public string UtcTime { get; set; } 51 | 52 | [JsonProperty("setting")] 53 | public string Setting { get; set; } 54 | 55 | [JsonProperty("res_ver")] 56 | public string ResVersion { get; set; } 57 | 58 | [JsonProperty("token")] 59 | public string Token { get; set; } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /MiniMe.Billing/BillingCryptoService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Cryptography; 3 | using System.Text; 4 | using MiniMe.Core.Extension; 5 | using OpenSSL.PrivateKeyDecoder; 6 | 7 | namespace MiniMe.Billing 8 | { 9 | public sealed class BillingCryptoService 10 | { 11 | private readonly RSACryptoServiceProvider _provider; 12 | 13 | public BillingCryptoService(byte[] privateKey) 14 | { 15 | var keyString = Encoding.ASCII.GetString(privateKey); 16 | 17 | var decoder = new OpenSSLPrivateKeyDecoder(); 18 | _provider = decoder.Decode(keyString); 19 | } 20 | 21 | public byte[] Sign(int value, string key) 22 | { 23 | Span buffer = stackalloc byte[15]; 24 | 25 | buffer.Write(value); 26 | buffer.Write(Encoding.ASCII.GetBytes(key), 4); 27 | 28 | return _provider.SignData(buffer.ToArray(), HashAlgorithmName.SHA1.Name); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /MiniMe.Billing/BillingServer.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Security.Cryptography.X509Certificates; 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.AspNetCore.Server.Kestrel.Core; 5 | using MiniMe.Core; 6 | using MiniMe.Core.AspNetCore.Hosting; 7 | using MiniMe.Core.Utilities; 8 | 9 | namespace MiniMe.Billing 10 | { 11 | [LoggerName("\u001b[38;5;4mBilling")] 12 | public sealed class BillingServer : HostServerBase 13 | { 14 | public BillingServer(IPEndPoint endPoint) : base(endPoint) 15 | { 16 | } 17 | 18 | protected override void ConfigureKestrel(KestrelServerOptions options) 19 | { 20 | options.Listen(EndPoint, listneOptions => 21 | { 22 | byte[] pfx = ResourceManager.GetResourceBytes("server.pfx"); 23 | var pfxCert = new X509Certificate2(pfx, "minime"); 24 | 25 | listneOptions.UseHttps(pfxCert); 26 | }); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /MiniMe.Billing/BillingStartup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using MiniMe.Core.AspNetCore.RequestDecompression; 5 | using MiniMe.Core.AspNetCore.Hosting; 6 | using MiniMe.Core.AspNetCore.Mvc.Formatters; 7 | using MiniMe.Core.Utilities; 8 | 9 | namespace MiniMe.Billing 10 | { 11 | public class BillingStartup : HostStartupBase 12 | { 13 | public override void Configure(IApplicationBuilder app) 14 | { 15 | app.UseRequestDecompression(); 16 | 17 | base.Configure(app); 18 | } 19 | 20 | public override void ConfigureServices(IServiceCollection services) 21 | { 22 | byte[] billingKey = ResourceManager.GetResourceBytes("billing.key"); 23 | 24 | services.AddSingleton(new BillingCryptoService(billingKey)); 25 | 26 | services.AddRequestDecompression(o => 27 | { 28 | o.Providers.Add(); 29 | }); 30 | 31 | base.ConfigureServices(services); 32 | } 33 | 34 | protected override void ConfigureControllers(MvcOptions options) 35 | { 36 | options.InputFormatters.Insert(0, new FormInputFormatter(true)); 37 | options.OutputFormatters.Insert(0, new FormOutputFormatter(true)); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /MiniMe.Billing/Controllers/BillingController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using MiniMe.Billing.Protocols; 3 | using MiniMe.Core.Utilities; 4 | 5 | namespace MiniMe.Billing.Controllers 6 | { 7 | [ApiController] 8 | [Route("/")] 9 | public class BillingController : ControllerBase 10 | { 11 | private const int playLimit = 1024; 12 | private const int nearFull = 0x00010200; 13 | 14 | private readonly BillingCryptoService _cryptoService; 15 | 16 | public BillingController(BillingCryptoService cryptoService) 17 | { 18 | _cryptoService = cryptoService; 19 | } 20 | 21 | [HttpPost("request")] 22 | public BillingResponse Request([FromBody] BillingRequest request) 23 | { 24 | byte[] signedPlayLimit = _cryptoService.Sign(playLimit, request.KeyChipId); 25 | byte[] signedNearFull = _cryptoService.Sign(nearFull, request.KeyChipId); 26 | 27 | return new BillingResponse 28 | { 29 | Result = 0, 30 | WaitTime = 100, 31 | LineLimit = 1, 32 | Message = string.Empty, 33 | PlayLimit = playLimit, 34 | PlayLimitSignature = HexUtility.BytesToHex(signedPlayLimit).ToLower(), 35 | NearFull = nearFull, 36 | NearFullSignature = HexUtility.BytesToHex(signedNearFull).ToLower(), 37 | ProtocolVersion = "1.000", 38 | FixLogCount = 0, 39 | FixInterval = 5, 40 | PlayHistory = "000000/0:000000/0:000000/0" 41 | }; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /MiniMe.Billing/MiniMe.Billing.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /MiniMe.Billing/Protocols/BillingRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.ObjectModel; 3 | using Newtonsoft.Json; 4 | 5 | namespace MiniMe.Billing.Protocols 6 | { 7 | public sealed class BillingRequest : Collection> 8 | { 9 | [JsonIgnore] 10 | public string KeyChipId => this[0]["keychipid"]; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /MiniMe.Billing/Protocols/BillingResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace MiniMe.Billing.Protocols 4 | { 5 | public sealed class BillingResponse 6 | { 7 | // 0 or 6 is success, anything else is an error 8 | [JsonProperty("result")] 9 | public int Result { get; set; } 10 | 11 | // ??? 12 | [JsonProperty("waittime")] 13 | public int WaitTime { get; set; } 14 | 15 | // Some sort of bandwidth-limiting thing..? 16 | // "line" refers to the shop's internet connection 17 | [JsonProperty("linelimit")] 18 | public int LineLimit { get; set; } 19 | 20 | // Server error message, copied to ALLNet debug log 21 | [JsonProperty("message")] 22 | public string Message { get; set; } 23 | 24 | // Keychip odometer limit. Game will lock out if the odometer reaches 25 | [JsonProperty("playlimit")] 26 | public int PlayLimit { get; set; } 27 | 28 | // RSA-SHA1 signature for new odometer limit. 29 | [JsonProperty("playlimitsig")] 30 | public string PlayLimitSignature { get; set; } 31 | 32 | // idk 33 | [JsonProperty("protocolver")] 34 | public string ProtocolVersion { get; set; } 35 | 36 | // A compound of two values. High 16 bits is the billing mode, low 16 bits 37 | // is the actual "nearfull" value. Not sure exactly what nearfull is, at a 38 | // guess it causes the client to check-in with the billing server when the 39 | // odometer is fewer than this many ticks away from its current limit. 40 | [JsonProperty("nearfull")] 41 | public int NearFull { get; set; } 42 | 43 | // RSA-SHA1 signature for the 32-bit nearfull value. 44 | [JsonProperty("nearfullsig")] 45 | public string NearFullSignature { get; set; } 46 | 47 | // ??? 48 | [JsonProperty("fixlogcnt")] 49 | public int FixLogCount { get; set; } 50 | 51 | // ??? 52 | [JsonProperty("fixinterval")] 53 | public int FixInterval { get; set; } 54 | 55 | // Monthly play count summary, visible in operator menu. The value below 56 | // is for a virgin machine fresh from the factory. Another example might be 57 | // 58 | // 201809/123:201810/456:201811/789 59 | // 60 | // which means 61 | // 62 | // Month 2018/09: 123 total plays 63 | // Month 2018/10: 456 total plays 64 | // Month 2018/11: 789 total plays 65 | [JsonProperty("playhistory")] 66 | public string PlayHistory { get; set; } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/ChunithmServer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using Microsoft.AspNetCore.Server.Kestrel.Core; 4 | using Microsoft.EntityFrameworkCore; 5 | using MiniMe.Chunithm.Data; 6 | using MiniMe.Core; 7 | using MiniMe.Core.AspNetCore.Hosting; 8 | 9 | namespace MiniMe.Chunithm 10 | { 11 | [LoggerName("\u001b[38;5;6mChunithm")] 12 | public sealed class ChunithmServer : HostServerBase, IDisposable 13 | { 14 | private ChunithmContext _context; 15 | 16 | public ChunithmServer(IPEndPoint endPoint) : base(endPoint) 17 | { 18 | _context = new ChunithmContext(); 19 | _context.Database.Migrate(); 20 | } 21 | 22 | protected override void ConfigureKestrel(KestrelServerOptions options) 23 | { 24 | options.AllowSynchronousIO = true; 25 | base.ConfigureKestrel(options); 26 | } 27 | 28 | public void Dispose() 29 | { 30 | _context?.Dispose(); 31 | _context = null; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/ChunithmStartup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using MiniMe.Chunithm.Data; 5 | using MiniMe.Chunithm.Middlewares; 6 | using MiniMe.Core; 7 | using MiniMe.Core.AspNetCore.ResponseCompression; 8 | using MiniMe.Core.AspNetCore.Hosting; 9 | using MiniMe.Core.AspNetCore.RequestDecompression; 10 | using MiniMe.Core.Repositories; 11 | 12 | namespace MiniMe.Chunithm 13 | { 14 | public class ChunithmStartup : HostStartupBase 15 | { 16 | public override void Configure(IApplicationBuilder app) 17 | { 18 | app.UseMiddleware(); 19 | app.UseRequestDecompression(); 20 | app.UseResponseCompression(); 21 | 22 | base.Configure(app); 23 | } 24 | 25 | public override void ConfigureServices(IServiceCollection services) 26 | { 27 | services 28 | .AddDbContext() 29 | .AddSingleton(MiniMeService.Get()) 30 | .AddRequestDecompression(o => 31 | { 32 | o.Providers.Add(); 33 | }) 34 | .AddResponseCompression(o => 35 | { 36 | o.Providers.Add(); 37 | }); 38 | 39 | base.ConfigureServices(services); 40 | } 41 | 42 | protected override void ConfigureJson(MvcNewtonsoftJsonOptions options) 43 | { 44 | options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/ChunithmUtility.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using MiniMe.Chunithm.Data.Models; 5 | using MiniMe.Chunithm.Protocols; 6 | 7 | namespace MiniMe.Chunithm 8 | { 9 | internal static class ChunithmUtility 10 | { 11 | public static int NextPagination(T[] array, ILimitedPagination pagination) 12 | { 13 | if (array.Length < pagination.MaxCount) 14 | { 15 | return -1; 16 | } 17 | 18 | return pagination.NextIndex + pagination.MaxCount; 19 | } 20 | 21 | public static IEnumerable PrepareDbObjects(IEnumerable source) where T : class, IDbObject 22 | { 23 | return source.Select(t => 24 | { 25 | if (t != null) 26 | { 27 | t.Id = Guid.NewGuid(); 28 | } 29 | 30 | return t; 31 | }); 32 | } 33 | 34 | public static IEnumerable PrepareDbObjects(IEnumerable source, Guid id) where T : class, IDbObject 35 | { 36 | return source.Select(t => 37 | { 38 | if (t != null) 39 | { 40 | t.Id = id; 41 | } 42 | 43 | return t; 44 | }); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Comparers/UserMusicEqualityComparer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using MiniMe.Chunithm.Protocols; 3 | 4 | namespace MiniMe.Chunithm.Comparers 5 | { 6 | public class UserMusicEqualityComparer : 7 | IEqualityComparer, 8 | IEqualityComparer 9 | { 10 | #region IEqualityComparer 11 | public bool Equals(UserMusic x, UserMusic y) 12 | { 13 | return x?.MusicId == y?.MusicId; 14 | } 15 | 16 | public int GetHashCode(UserMusic obj) 17 | { 18 | return obj?.MusicId ?? -1; 19 | } 20 | #endregion 21 | 22 | #region IEqualityComparer 23 | public bool Equals(Data.Models.UserMusic x, Data.Models.UserMusic y) 24 | { 25 | return x?.Id == y?.Id || x?.MusicId == y?.MusicId; 26 | } 27 | 28 | public int GetHashCode(Data.Models.UserMusic obj) 29 | { 30 | return obj?.GetHashCode() ?? -1; 31 | } 32 | #endregion 33 | 34 | #region Singleton 35 | public static UserMusicEqualityComparer Instance => _instance ??= new UserMusicEqualityComparer(); 36 | 37 | private static UserMusicEqualityComparer _instance; 38 | 39 | private UserMusicEqualityComparer() 40 | { 41 | } 42 | #endregion 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Data/ChunithmContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using Microsoft.EntityFrameworkCore; 6 | using MiniMe.Chunithm.Data.Models; 7 | using MiniMe.Core; 8 | using Serilog.Extensions.Logging; 9 | 10 | namespace MiniMe.Chunithm.Data 11 | { 12 | public class ChunithmContext : DbContext 13 | { 14 | public DbSet Profiles { get; set; } 15 | 16 | protected override void OnConfiguring(DbContextOptionsBuilder options) 17 | { 18 | options.UseSqlite($"Data Source={MiniMeEnvironment.GetDataFile("chunithm.db")}"); 19 | } 20 | 21 | protected override void OnModelCreating(ModelBuilder modelBuilder) 22 | { 23 | modelBuilder.Entity(builder => 24 | { 25 | builder 26 | .HasOne(data => data.Profile) 27 | .WithOne(profile => profile.DataEx) 28 | .HasForeignKey(data => data.Id); 29 | 30 | builder 31 | .HasIndex(e => e.Id) 32 | .IsUnique(); 33 | }); 34 | 35 | modelBuilder.Entity(builder => 36 | { 37 | builder 38 | .HasOne(option => option.Profile) 39 | .WithOne(profile => profile.GameOption) 40 | .HasForeignKey(option => option.Id); 41 | 42 | builder 43 | .HasIndex(e => e.Id) 44 | .IsUnique(); 45 | }); 46 | 47 | modelBuilder.Entity(builder => 48 | { 49 | builder 50 | .HasOne(optionEx => optionEx.Profile) 51 | .WithOne(profile => profile.GameOptionEx) 52 | .HasForeignKey(optionEx => optionEx.Id); 53 | 54 | builder 55 | .HasIndex(e => e.Id) 56 | .IsUnique(); 57 | }); 58 | 59 | modelBuilder.Entity(builder => 60 | { 61 | builder 62 | .HasOne(activity => activity.Profile) 63 | .WithMany(profile => profile.Activities) 64 | .HasForeignKey(activity => activity.ProfileId); 65 | 66 | builder 67 | .HasIndex(e => new { e.ProfileId, e.Kind, e.ActivityId }) 68 | .IsUnique(); 69 | }); 70 | 71 | modelBuilder.Entity(builder => 72 | { 73 | builder 74 | .HasOne(character => character.Profile) 75 | .WithMany(profile => profile.Characters) 76 | .HasForeignKey(character => character.ProfileId); 77 | 78 | builder 79 | .HasIndex(e => new { e.ProfileId, e.CharacterId }) 80 | .IsUnique(); 81 | }); 82 | 83 | modelBuilder.Entity(builder => 84 | { 85 | builder 86 | .HasOne(course => course.Profile) 87 | .WithMany(profile => profile.Courses) 88 | .HasForeignKey(course => course.ProfileId); 89 | 90 | builder 91 | .HasIndex(e => new { e.ProfileId, e.CourseId }) 92 | .IsUnique(); 93 | }); 94 | 95 | modelBuilder.Entity(builder => 96 | { 97 | builder 98 | .HasOne(duelList => duelList.Profile) 99 | .WithMany(userProfile => userProfile.DuelLists) 100 | .HasForeignKey(duelList => duelList.ProfileId); 101 | 102 | builder 103 | .HasIndex(e => new { e.ProfileId, e.DuelId }) 104 | .IsUnique(); 105 | }); 106 | 107 | modelBuilder.Entity(builder => 108 | { 109 | builder 110 | .HasOne(item => item.Profile) 111 | .WithMany(profile => profile.Items) 112 | .HasForeignKey(item => item.ProfileId); 113 | 114 | builder 115 | .HasIndex(e => new { e.ProfileId, e.ItemId, e.ItemKind }) 116 | .IsUnique(); 117 | }); 118 | 119 | modelBuilder.Entity(builder => 120 | { 121 | builder 122 | .HasOne(map => map.Profile) 123 | .WithMany(profile => profile.Maps) 124 | .HasForeignKey(map => map.ProfileId); 125 | 126 | builder 127 | .HasIndex(e => new { e.ProfileId, e.MapId }) 128 | .IsUnique(); 129 | }); 130 | 131 | modelBuilder.Entity(builder => 132 | { 133 | builder 134 | .HasOne(music => music.Profile) 135 | .WithMany(profile => profile.Musics) 136 | .HasForeignKey(music => music.ProfileId); 137 | 138 | builder 139 | .HasIndex(e => new { e.ProfileId, e.MusicId, e.Level }) 140 | .IsUnique(); 141 | }); 142 | 143 | modelBuilder.Entity() 144 | .HasOne(log => log.Profile) 145 | .WithMany(profile => profile.PlayLogs) 146 | .HasForeignKey(plog => plog.ProfileId); 147 | } 148 | 149 | public UserProfile FindProfile([AllowNull] Guid? aimeId) 150 | { 151 | return FindProfileWithQuery(aimeId, null); 152 | } 153 | 154 | public UserProfile FindProfileWithAllData([AllowNull] Guid? aimeId) 155 | { 156 | return FindProfileWithQuery(aimeId, ps => ps 157 | .Include(p => p.DataEx) 158 | .Include(p => p.GameOption) 159 | .Include(p => p.GameOptionEx) 160 | .Include(p => p.Activities) 161 | .Include(p => p.Characters) 162 | .Include(p => p.Courses) 163 | .Include(p => p.DuelLists) 164 | .Include(p => p.Items) 165 | .Include(p => p.Maps) 166 | .Include(p => p.Musics) 167 | .Include(p => p.PlayLogs)); 168 | } 169 | 170 | public UserProfile FindProfileWithData( 171 | [AllowNull] Guid? aimeId, 172 | [NotNull] Expression> include) 173 | { 174 | return FindProfileWithQuery(aimeId, ps => ps.Include(include)); 175 | } 176 | 177 | public UserProfile FindProfileWithQuery( 178 | [AllowNull] Guid? aimeId, 179 | [AllowNull] Func, IQueryable> wrapper) 180 | { 181 | if (!aimeId.HasValue) 182 | return null; 183 | 184 | return (wrapper == null ? Profiles : wrapper(Profiles)) 185 | .SingleOrDefault(d => d.AimeId == aimeId); 186 | } 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Data/Models/Common/IDbObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MiniMe.Chunithm.Data.Models 4 | { 5 | public interface IDbObject 6 | { 7 | Guid Id { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Data/Models/Common/IDbProfileObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MiniMe.Chunithm.Data.Models 4 | { 5 | public interface IDbProfileObject : IDbObject 6 | { 7 | Guid ProfileId { get; set; } 8 | 9 | UserProfile Profile { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Data/Models/UserActivity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace MiniMe.Chunithm.Data.Models 6 | { 7 | public class UserActivity : Protocols.UserActivity, IDbProfileObject 8 | { 9 | [Key, Required] 10 | [DatabaseGenerated(DatabaseGeneratedOption.None)] 11 | public Guid Id { get; set; } 12 | 13 | [Required] 14 | public Guid ProfileId { get; set; } 15 | 16 | public UserProfile Profile { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Data/Models/UserCharacter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace MiniMe.Chunithm.Data.Models 6 | { 7 | public class UserCharacter : Protocols.UserCharacter, IDbProfileObject 8 | { 9 | [Key, Required] 10 | [DatabaseGenerated(DatabaseGeneratedOption.None)] 11 | public Guid Id { get; set; } 12 | 13 | [Required] 14 | public Guid ProfileId { get; set; } 15 | 16 | public UserProfile Profile { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Data/Models/UserCourse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace MiniMe.Chunithm.Data.Models 6 | { 7 | public class UserCourse : Protocols.UserCourse, IDbProfileObject 8 | { 9 | [Key, Required] 10 | [DatabaseGenerated(DatabaseGeneratedOption.None)] 11 | public Guid Id { get; set; } 12 | 13 | [Required] 14 | public Guid ProfileId { get; set; } 15 | 16 | public UserProfile Profile { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Data/Models/UserDataEx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace MiniMe.Chunithm.Data.Models 6 | { 7 | public class UserDataEx : Protocols.UserDataEx, IDbProfileObject 8 | { 9 | [Key, Required] 10 | [DatabaseGenerated(DatabaseGeneratedOption.None)] 11 | public Guid Id { get; set; } 12 | 13 | Guid IDbProfileObject.ProfileId 14 | { 15 | get => Id; 16 | set => Id = value; 17 | } 18 | 19 | public UserProfile Profile { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Data/Models/UserDuelList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace MiniMe.Chunithm.Data.Models 6 | { 7 | public class UserDuelList : Protocols.UserDuelList, IDbProfileObject 8 | { 9 | [Key, Required] 10 | [DatabaseGenerated(DatabaseGeneratedOption.None)] 11 | public Guid Id { get; set; } 12 | 13 | [Required] 14 | public Guid ProfileId { get; set; } 15 | 16 | public UserProfile Profile { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Data/Models/UserGameOption.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace MiniMe.Chunithm.Data.Models 6 | { 7 | public class UserGameOption : Protocols.UserGameOption, IDbProfileObject 8 | { 9 | [Key, Required] 10 | [DatabaseGenerated(DatabaseGeneratedOption.None)] 11 | public Guid Id { get; set; } 12 | 13 | Guid IDbProfileObject.ProfileId 14 | { 15 | get => Id; 16 | set => Id = value; 17 | } 18 | 19 | public UserProfile Profile { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Data/Models/UserGameOptionEx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace MiniMe.Chunithm.Data.Models 6 | { 7 | public class UserGameOptionEx : Protocols.UserGameOptionEx, IDbProfileObject 8 | { 9 | [Key, Required] 10 | [DatabaseGenerated(DatabaseGeneratedOption.None)] 11 | public Guid Id { get; set; } 12 | 13 | Guid IDbProfileObject.ProfileId 14 | { 15 | get => Id; 16 | set => Id = value; 17 | } 18 | 19 | public UserProfile Profile { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Data/Models/UserItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace MiniMe.Chunithm.Data.Models 6 | { 7 | public class UserItem : Protocols.UserItem, IDbProfileObject 8 | { 9 | [Key, Required] 10 | [DatabaseGenerated(DatabaseGeneratedOption.None)] 11 | public Guid Id { get; set; } 12 | 13 | [Required] 14 | public Guid ProfileId { get; set; } 15 | 16 | public UserProfile Profile { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Data/Models/UserMap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace MiniMe.Chunithm.Data.Models 6 | { 7 | public class UserMap : Protocols.UserMap, IDbProfileObject 8 | { 9 | [Key, Required] 10 | [DatabaseGenerated(DatabaseGeneratedOption.None)] 11 | public Guid Id { get; set; } 12 | 13 | [Required] 14 | public Guid ProfileId { get; set; } 15 | 16 | public UserProfile Profile { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Data/Models/UserMusic.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace MiniMe.Chunithm.Data.Models 6 | { 7 | public class UserMusic : Protocols.UserMusic, IDbProfileObject 8 | { 9 | [Key, Required] 10 | [DatabaseGenerated(DatabaseGeneratedOption.None)] 11 | public Guid Id { get; set; } 12 | 13 | [Required] 14 | public Guid ProfileId { get; set; } 15 | 16 | public UserProfile Profile { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Data/Models/UserPlayLog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace MiniMe.Chunithm.Data.Models 6 | { 7 | public class UserPlayLog : Protocols.UserPlayLog, IDbProfileObject 8 | { 9 | [Key, Required] 10 | [DatabaseGenerated(DatabaseGeneratedOption.None)] 11 | public Guid Id { get; set; } 12 | 13 | [Required] 14 | public Guid ProfileId { get; set; } 15 | 16 | public UserProfile Profile { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Data/Models/UserProfile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | 6 | namespace MiniMe.Chunithm.Data.Models 7 | { 8 | public class UserProfile : Protocols.UserProfile, IDbObject 9 | { 10 | [Key, Required] 11 | [DatabaseGenerated(DatabaseGeneratedOption.None)] 12 | public Guid Id { get; set; } 13 | 14 | [Required] 15 | public Guid AimeId { get; set; } 16 | 17 | public UserDataEx DataEx { get; set; } 18 | 19 | public UserGameOption GameOption { get; set; } 20 | 21 | public UserGameOptionEx GameOptionEx { get; set; } 22 | 23 | public IList Activities { get; set; } 24 | 25 | public IList Characters { get; set; } 26 | 27 | public IList Courses { get; set; } 28 | 29 | public IList DuelLists { get; set; } 30 | 31 | public IList Items { get; set; } 32 | 33 | public IList Maps { get; set; } 34 | 35 | public IList Musics { get; set; } 36 | 37 | public IList PlayLogs { get; set; } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Middlewares/QuirksMiddleware.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.AspNetCore.Http; 3 | using MiniMe.Core.AspNetCore.Middleswares; 4 | 5 | namespace MiniMe.Chunithm.Middlewares 6 | { 7 | public class QuirksMiddleware : MiddlewareBase 8 | { 9 | public QuirksMiddleware(RequestDelegate next) : base(next) 10 | { 11 | } 12 | 13 | protected override Task BeforeInvoke(HttpContext context) 14 | { 15 | if (!context.Request.Headers.ContainsKey("x-debug")) 16 | { 17 | context.Request.Headers["Accept-Encoding"] = "deflate"; 18 | } 19 | 20 | return Task.CompletedTask; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/MiniMe.Chunithm.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | runtime; build; native; contentfiles; analyzers; buildtransitive 16 | all 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/GameChargeItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MiniMe.Chunithm.Protocols 4 | { 5 | public class GameChargeItem 6 | { 7 | public int OrderId { get; set; } 8 | 9 | public int ChargeId { get; set; } 10 | 11 | public int Price { get; set; } 12 | 13 | public DateTimeOffset StartDate { get; set; } 14 | 15 | public DateTimeOffset EndDate { get; set; } 16 | 17 | public int SalePrice { get; set; } 18 | 19 | public DateTimeOffset SaleStartDate { get; set; } 20 | 21 | public DateTimeOffset SaleEndDate { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/GameEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MiniMe.Chunithm.Protocols 4 | { 5 | public class GameEvent 6 | { 7 | public int Type { get; set; } 8 | 9 | public int Id { get; set; } 10 | 11 | public DateTime StartDate { get; set; } 12 | 13 | public DateTime EndDate { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/GameMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MiniMe.Chunithm.Protocols 4 | { 5 | public class GameMessage 6 | { 7 | public int Type { get; set; } 8 | 9 | public int Id { get; set; } 10 | 11 | public string Message { get; set; } 12 | 13 | public DateTimeOffset StartDate { get; set; } 14 | 15 | public DateTimeOffset EndDate { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/GameRanking.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GameRanking 4 | { 5 | public int Id { get; set; } 6 | 7 | public int Point { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/GameSale.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MiniMe.Chunithm.Protocols 4 | { 5 | public class GameSale 6 | { 7 | public int OrderId { get; set; } 8 | 9 | public int Type { get; set; } 10 | 11 | public int Id { get; set; } 12 | 13 | public int Rate { get; set; } 14 | 15 | public DateTimeOffset StartDate { get; set; } 16 | 17 | public DateTimeOffset EndDate { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/ILimitedPagination.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public interface ILimitedPagination : IPagination 4 | { 5 | int MaxCount { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/IPagination.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public interface IPagination 4 | { 5 | int NextIndex { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GameLoginRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GameLoginRequest 4 | { 5 | public int UserId { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GameLogoutRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GameLogoutRequest 4 | { 5 | public int UserId { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetGameChargeRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetGameChargeRequest 4 | { 5 | public bool IsAllSale { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetGameEventRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetGameEventRequest 4 | { 5 | // FIXME 6 | 7 | public int Type { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetGameIdlistRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetGameIdlistRequest 4 | { 5 | public int Type { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetGameMessageRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetGameMessageRequest 4 | { 5 | public int Type { get; set; } 6 | 7 | public bool IsAllMessage { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetGameRankingRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetGameRankingRequest 4 | { 5 | public int Type { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetGameSaleRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetGameSaleRequest 4 | { 5 | public int Type { get; set; } 6 | 7 | public string IsAllScale { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetGameSettingRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetGameSettingRequest 4 | { 5 | public string PlaceId { get; set; } 6 | 7 | public string ClientId { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetUserActivityRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserActivityRequest 4 | { 5 | public int UserId { get; set; } 6 | 7 | public int Kind { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetUserCharacterRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserCharacterRequest : ILimitedPagination 4 | { 5 | public int UserId { get; set; } 6 | 7 | public int NextIndex { get; set; } 8 | 9 | public int MaxCount { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetUserChargeRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserChargeRequest 4 | { 5 | public int UserId { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetUserCourseRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserCourseRequest : ILimitedPagination 4 | { 5 | public int UserId { get; set; } 6 | 7 | public int NextIndex { get; set; } 8 | 9 | public int MaxCount { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetUserDataExRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserDataExRequest 4 | { 5 | public int UserId { get; set; } 6 | 7 | public bool IsAdmin { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetUserDataRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserDataRequest 4 | { 5 | public int UserId { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetUserDuelRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserDuelRequest 4 | { 5 | public int UserId { get; set; } 6 | 7 | public int DuelId { get; set; } 8 | 9 | public bool IsAllDuel { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetUserItemRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserItemRequest 4 | { 5 | public int UserId { get; set; } 6 | 7 | public long NextIndex { get; set; } 8 | 9 | public int MaxCount { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetUserMapRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserMapRequest 4 | { 5 | public int UserId { get; set; } 6 | 7 | public bool IsAllMap { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetUserMusicRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserMusicRequest : ILimitedPagination 4 | { 5 | public int UserId { get; set; } 6 | 7 | public int NextIndex { get; set; } 8 | 9 | public int MaxCount { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetUserOptionExRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserOptionExRequest 4 | { 5 | public int UserId { get; set; } 6 | 7 | public bool IsAdmin { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetUserOptionRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserOptionRequest 4 | { 5 | public int UserId { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetUserPreviewRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserPreviewRequest 4 | { 5 | public int UserId { get; set; } 6 | 7 | public string SegaIdAuthKey { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetUserRecentRatingRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserRecentRatingRequest 4 | { 5 | public int UserId { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/GetUserRegionRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserRegionRequest 4 | { 5 | // FIXME 6 | 7 | public int UserId { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/UpsertClientBookkeepingRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class UpsertClientBookkeepingRequest 4 | { 5 | // FIXME 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/UpsertClientDevelopRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class UpsertClientDevelopRequest 4 | { 5 | // FIXME 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/UpsertClientErrorRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class UpsertClientErrorRequest 4 | { 5 | // FIXME 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/UpsertClientSettingRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MiniMe.Chunithm.Protocols 4 | { 5 | public class UpsertClientSettingRequest 6 | { 7 | public Payload ClientSetting { get; set; } 8 | 9 | public class Payload 10 | { 11 | public string PlaceId { get; set; } 12 | 13 | public string ClientId { get; set; } 14 | 15 | public string PlaceName { get; set; } 16 | 17 | public string RegionId { get; set; } 18 | 19 | public string RegionName { get; set; } 20 | 21 | public string BordId { get; set; } 22 | 23 | public Version RomVersion { get; set; } 24 | 25 | public Version DataVersion { get; set; } 26 | 27 | public int DumpFileNum { get; set; } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/UpsertClientTestModeRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class UpsertClientTestModeRequest 4 | { 5 | public Payload ClientTestMode { get; set; } 6 | 7 | public class Payload 8 | { 9 | public string PlaceId { get; set; } 10 | 11 | public string ClientId { get; set; } 12 | 13 | public string UpdateDate { get; set; } 14 | 15 | public string IsDelivery { get; set; } 16 | 17 | public string GroupId { get; set; } 18 | 19 | public string GroupRole { get; set; } 20 | 21 | public string ContinueMode { get; set; } 22 | 23 | public string SelectMusicTime { get; set; } 24 | 25 | public string AdvertiseVolume { get; set; } 26 | 27 | public string EventMode { get; set; } 28 | 29 | public string EventMusicNum { get; set; } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Request/UpsertUserAllRequest.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class UpsertUserAllRequest 4 | { 5 | public int UserId { get; set; } 6 | 7 | public Payload UpsertUserAll { get; set; } 8 | 9 | public class Payload 10 | { 11 | public UserProfile[] UserData { get; set; } 12 | 13 | public UserGameOption[] UserGameOption { get; set; } 14 | 15 | public UserGameOptionEx[] UserGameOptionEx { get; set; } 16 | 17 | public UserMap[] UserMapList { get; set; } 18 | 19 | public UserCharacter[] UserCharacterList { get; set; } 20 | 21 | public UserItem[] UserItemList { get; set; } 22 | 23 | public UserMusic[] UserMusicDetailList { get; set; } 24 | 25 | public UserActivity[] UserActivityList { get; set; } 26 | 27 | public UserRecentRating[] UserRecentRatingList { get; set; } 28 | 29 | public UserPlayLog[] UserPlayLogList { get; set; } 30 | 31 | public UserCourse[] UserCourseList { get; set; } 32 | 33 | public UserDataEx[] UserDataEx { get; set; } 34 | 35 | public UserDuelList[] UserDuelList { get; set; } 36 | 37 | public string IsNewMapList { get; set; } 38 | 39 | public string IsNewCharacterList { get; set; } 40 | 41 | public string IsNewMusicDetailList { get; set; } 42 | 43 | public string IsNewItemList { get; set; } 44 | 45 | public string IsNewCourseList { get; set; } 46 | 47 | public string IsNewDuelList { get; set; } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GameLoginResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GameLoginResponse 4 | { 5 | public int ReturnCode { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GameLogoutResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GameLogoutResponse 4 | { 5 | public int ReturnCode { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetGameChargeResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetGameChargeResponse 4 | { 5 | public int Length { get; set; } 6 | 7 | public GameChargeItem[] GameChargeList { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetGameEventResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetGameEventResponse 4 | { 5 | public int Type { get; set; } 6 | 7 | public int Length { get; set; } 8 | 9 | public GameEvent[] GameEventList { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetGameIdlistResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetGameIdlistResponse 4 | { 5 | public int Type { get; set; } 6 | 7 | public int Length { get; set; } 8 | 9 | public object[] GameIdlistList { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetGameMessageResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetGameMessageResponse 4 | { 5 | public int Type { get; set; } 6 | 7 | public int Length { get; set; } 8 | 9 | public GameMessage[] GameMessageList { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetGameRankingResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetGameRankingResponse 4 | { 5 | public int Type { get; set; } 6 | 7 | public GameRanking[] GameRankingList { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetGameSaleResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetGameSaleResponse 4 | { 5 | public int Type { get; set; } 6 | 7 | public int Length { get; set; } 8 | 9 | public GameSale[] GameSaleList { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetGameSettingResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MiniMe.Chunithm.Protocols 4 | { 5 | public class GetGameSettingResponse 6 | { 7 | public Payload GameSetting { get; set; } 8 | 9 | public bool IsDumpUpload { get; set; } 10 | 11 | public bool IsAou { get; set; } 12 | 13 | public class Payload 14 | { 15 | public string DataVersion { get; set; } 16 | 17 | public bool IsMaintenance { get; set; } 18 | 19 | public int RequestInterval { get; set; } 20 | 21 | public DateTime RebootStartTime { get; set; } 22 | 23 | public DateTime RebootEndTime { get; set; } 24 | 25 | public bool IsBackgroundDistribute { get; set; } 26 | 27 | public int MaxCountCharacter { get; set; } 28 | 29 | public int MaxCountItem { get; set; } 30 | 31 | public int MaxCountMusic { get; set; } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetUserActivityResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserActivityResponse 4 | { 5 | public int UserId { get; set; } 6 | 7 | public int Length { get; set; } 8 | 9 | public int Kind { get; set; } 10 | 11 | public UserActivity[] UserActivityList { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetUserCharacterResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserCharacterResponse : IPagination 4 | { 5 | public int UserId { get; set; } 6 | 7 | public int Length { get; set; } 8 | 9 | public int NextIndex { get; set; } 10 | 11 | public UserCharacter[] UserCharacterList { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetUserChargeResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserChargeResponse 4 | { 5 | public int UserId { get; set; } 6 | 7 | public int Length { get; set; } 8 | 9 | public object[] UserChargeList { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetUserCourseResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserCourseResponse : IPagination 4 | { 5 | public int UserId { get; set; } 6 | 7 | public int Length { get; set; } 8 | 9 | public int NextIndex { get; set; } 10 | 11 | public UserCourse[] UserCourseList { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetUserDataExResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserDataExResponse 4 | { 5 | public int UserId { get; set; } 6 | 7 | public UserDataEx UserDataEx { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetUserDataResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserDataResponse 4 | { 5 | public int UserId { get; set; } 6 | 7 | public UserProfile UserData { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetUserDuelResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserDuelResponse 4 | { 5 | public int UserId { get; set; } 6 | 7 | public int Length { get; set; } 8 | 9 | public UserDuelList[] UserDuelList { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetUserItemResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserItemResponse 4 | { 5 | public int UserId { get; set; } 6 | 7 | public int Length { get; set; } 8 | 9 | public long NextIndex { get; set; } 10 | 11 | public int ItemKind { get; set; } 12 | 13 | public UserItem[] UserItemList { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetUserMapResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserMapResponse 4 | { 5 | public int UserId { get; set; } 6 | 7 | public int Length { get; set; } 8 | 9 | public UserMap[] UserMapList { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetUserMusicResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserMusicResponse : IPagination 4 | { 5 | public int UserId { get; set; } 6 | 7 | public int Length { get; set; } 8 | 9 | public int NextIndex { get; set; } 10 | 11 | public UserMusic[] UserMusicList { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetUserOptionExResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserOptionExResponse 4 | { 5 | public int UserId { get; set; } 6 | 7 | public UserGameOptionEx UserGameOptionEx { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetUserOptionResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserOptionResponse 4 | { 5 | public int UserId { get; set; } 6 | 7 | public UserGameOption UserGameOption { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetUserPreviewResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MiniMe.Chunithm.Protocols 4 | { 5 | public class GetUserPreviewResponse 6 | { 7 | public int UserId { get; set; } 8 | 9 | public bool IsLogin { get; set; } 10 | 11 | /// 12 | /// yyyy-MM-dd hh:mm:ss 13 | /// 14 | public DateTime LastLoginDate { get; set; } 15 | 16 | #region UserData 17 | public string UserName { get; set; } 18 | 19 | public int ReincarnationNum { get; set; } 20 | 21 | public int Level { get; set; } 22 | 23 | public int Exp { get; set; } 24 | 25 | public int PlayerRating { get; set; } 26 | 27 | public string LastGameId { get; set; } 28 | 29 | public string LastRomVersion { get; set; } 30 | 31 | public string LastDataVersion { get; set; } 32 | 33 | public DateTime LastPlayDate { get; set; } 34 | 35 | public int TrophyId { get; set; } 36 | #endregion 37 | 38 | #region Selected UserCharacter 39 | public UserCharacter UserCharacter { get; set; } 40 | #endregion 41 | 42 | #region UserGameOption 43 | public int PlayerLevel { get; set; } 44 | 45 | public int Rating { get; set; } 46 | 47 | public int Headphone { get; set; } 48 | #endregion 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetUserRecentRatingResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserRecentRatingResponse 4 | { 5 | public int UserId { get; set; } 6 | 7 | public int Length { get; set; } 8 | 9 | public UserRecentRating[] UserRecentRatingList { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/GetUserRegionResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class GetUserRegionResponse 4 | { 5 | public int UserId { get; set; } 6 | 7 | public int Length { get; set; } 8 | 9 | public UserRegion[] UserRegionList { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/UpsertClientBookkeepingResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class UpsertClientBookkeepingResponse 4 | { 5 | public int ReturnCode { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/UpsertClientDevelopResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class UpsertClientDevelopResponse 4 | { 5 | public int ReturnCode { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/UpsertClientErrorResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class UpsertClientErrorResponse 4 | { 5 | public int ReturnCode { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/UpsertClientSettingResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class UpsertClientSettingResponse 4 | { 5 | public int ReturnCode { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/UpsertClientTestmodeResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class UpsertClientTestmodeResponse 4 | { 5 | public int ReturnCode { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/Response/UpsertUserAllResponse.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class UpsertUserAllResponse 4 | { 5 | public int ReturnCode { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/UserActivity.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace MiniMe.Chunithm.Protocols 4 | { 5 | public class UserActivity 6 | { 7 | public virtual int Kind { get; set; } 8 | 9 | [JsonProperty("id")] 10 | public virtual int ActivityId { get; set; } 11 | 12 | public virtual int SortNumber { get; set; } 13 | 14 | public virtual int Param1 { get; set; } 15 | 16 | public virtual int Param2 { get; set; } 17 | 18 | public virtual int Param3 { get; set; } 19 | 20 | public virtual int Param4 { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/UserCharacter.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class UserCharacter 4 | { 5 | public virtual int CharacterId { get; set; } 6 | 7 | public virtual int PlayCount { get; set; } 8 | 9 | public virtual int Level { get; set; } 10 | 11 | public virtual int SkillId { get; set; } 12 | 13 | public virtual int FriendshipExp { get; set; } 14 | 15 | public virtual bool IsValid { get; set; } 16 | 17 | public virtual bool IsNewMark { get; set; } 18 | 19 | public virtual int Param1 { get; set; } 20 | 21 | public virtual int Param2 { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/UserCourse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MiniMe.Chunithm.Protocols 4 | { 5 | public class UserCourse 6 | { 7 | public virtual int CourseId { get; set; } 8 | 9 | public virtual int ClassId { get; set; } 10 | 11 | public virtual int PlayCount { get; set; } 12 | 13 | public virtual int ScoreMax { get; set; } 14 | 15 | public virtual bool IsFullCombo { get; set; } 16 | 17 | public virtual bool IsAllJustice { get; set; } 18 | 19 | public virtual bool IsSuccess { get; set; } 20 | 21 | public virtual int ScoreRank { get; set; } 22 | 23 | public virtual int EventId { get; set; } 24 | 25 | public virtual DateTimeOffset LastPlayDate { get; set; } 26 | 27 | public virtual int Param1 { get; set; } 28 | 29 | public virtual int Param2 { get; set; } 30 | 31 | public virtual int Param3 { get; set; } 32 | 33 | public virtual int Param4 { get; set; } 34 | 35 | public virtual bool IsClear { get; set; } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/UserDataEx.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class UserDataEx 4 | { 5 | public virtual string CompatibleCmVersion { get; set; } 6 | 7 | public virtual int Medal { get; set; } 8 | 9 | public virtual int MapIconId { get; set; } 10 | 11 | public virtual int VoiceId { get; set; } 12 | 13 | public virtual int Ext1 { get; set; } 14 | 15 | public virtual int Ext2 { get; set; } 16 | 17 | public virtual int Ext3 { get; set; } 18 | 19 | public virtual int Ext4 { get; set; } 20 | 21 | public virtual int Ext5 { get; set; } 22 | 23 | public virtual int Ext6 { get; set; } 24 | 25 | public virtual int Ext7 { get; set; } 26 | 27 | public virtual int Ext8 { get; set; } 28 | 29 | public virtual int Ext9 { get; set; } 30 | 31 | public virtual int Ext10 { get; set; } 32 | 33 | public virtual int Ext11 { get; set; } 34 | 35 | public virtual int Ext12 { get; set; } 36 | 37 | public virtual int Ext13 { get; set; } 38 | 39 | public virtual int Ext14 { get; set; } 40 | 41 | public virtual int Ext15 { get; set; } 42 | 43 | public virtual int Ext16 { get; set; } 44 | 45 | public virtual int Ext17 { get; set; } 46 | 47 | public virtual int Ext18 { get; set; } 48 | 49 | public virtual int Ext19 { get; set; } 50 | 51 | public virtual int Ext20 { get; set; } 52 | 53 | public virtual string ExtStr1 { get; set; } 54 | 55 | public virtual string ExtStr2 { get; set; } 56 | 57 | public virtual string ExtStr3 { get; set; } 58 | 59 | public virtual string ExtStr4 { get; set; } 60 | 61 | public virtual string ExtStr5 { get; set; } 62 | 63 | public virtual long ExtLong1 { get; set; } 64 | 65 | public virtual long ExtLong2 { get; set; } 66 | 67 | public virtual long ExtLong3 { get; set; } 68 | 69 | public virtual long ExtLong4 { get; set; } 70 | 71 | public virtual long ExtLong5 { get; set; } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/UserDuelList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MiniMe.Chunithm.Protocols 4 | { 5 | public class UserDuelList 6 | { 7 | public virtual int DuelId { get; set; } 8 | 9 | public virtual int Progress { get; set; } 10 | 11 | public virtual int Point { get; set; } 12 | 13 | public virtual bool IsClear { get; set; } 14 | 15 | public virtual DateTimeOffset LastPlayDate { get; set; } 16 | 17 | public virtual int Param1 { get; set; } 18 | 19 | public virtual int Param2 { get; set; } 20 | 21 | public virtual int Param3 { get; set; } 22 | 23 | public virtual int Param4 { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/UserGameOption.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class UserGameOption 4 | { 5 | public virtual int BgInfo { get; set; } 6 | 7 | public virtual int FieldColor { get; set; } 8 | 9 | public virtual int GuideSound { get; set; } 10 | 11 | public virtual int SoundEffect { get; set; } 12 | 13 | public virtual int GuideLine { get; set; } 14 | 15 | public virtual int Speed { get; set; } 16 | 17 | public virtual int OptionSet { get; set; } 18 | 19 | public virtual int Matching { get; set; } 20 | 21 | public virtual int JudgePos { get; set; } 22 | 23 | public virtual int Rating { get; set; } 24 | 25 | public virtual int JudgeJustice { get; set; } 26 | 27 | public virtual int JudgeAttack { get; set; } 28 | 29 | public virtual int Headphone { get; set; } 30 | 31 | public virtual int PlayerLevel { get; set; } 32 | 33 | public virtual int SuccessTap { get; set; } 34 | 35 | public virtual int SuccessExTap { get; set; } 36 | 37 | public virtual int SuccessSlideHold { get; set; } 38 | 39 | public virtual int SuccessAir { get; set; } 40 | 41 | public virtual int SuccessFlick { get; set; } 42 | 43 | public virtual int SuccessSkill { get; set; } 44 | 45 | public virtual int SuccessTapTimbre { get; set; } 46 | 47 | public virtual int Privacy { get; set; } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/UserGameOptionEx.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class UserGameOptionEx 4 | { 5 | public virtual int Ext1 { get; set; } 6 | 7 | public virtual int Ext2 { get; set; } 8 | 9 | public virtual int Ext3 { get; set; } 10 | 11 | public virtual int Ext4 { get; set; } 12 | 13 | public virtual int Ext5 { get; set; } 14 | 15 | public virtual int Ext6 { get; set; } 16 | 17 | public virtual int Ext7 { get; set; } 18 | 19 | public virtual int Ext8 { get; set; } 20 | 21 | public virtual int Ext9 { get; set; } 22 | 23 | public virtual int Ext10 { get; set; } 24 | 25 | public virtual int Ext11 { get; set; } 26 | 27 | public virtual int Ext12 { get; set; } 28 | 29 | public virtual int Ext13 { get; set; } 30 | 31 | public virtual int Ext14 { get; set; } 32 | 33 | public virtual int Ext15 { get; set; } 34 | 35 | public virtual int Ext16 { get; set; } 36 | 37 | public virtual int Ext17 { get; set; } 38 | 39 | public virtual int Ext18 { get; set; } 40 | 41 | public virtual int Ext19 { get; set; } 42 | 43 | public virtual int Ext20 { get; set; } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/UserItem.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class UserItem 4 | { 5 | public virtual int ItemKind { get; set; } 6 | 7 | public virtual int ItemId { get; set; } 8 | 9 | public virtual int Stock { get; set; } 10 | 11 | public virtual bool IsValid { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/UserMap.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class UserMap 4 | { 5 | public virtual int MapId { get; set; } 6 | 7 | public virtual int Position { get; set; } 8 | 9 | public virtual bool IsClear { get; set; } 10 | 11 | public virtual int AreaId { get; set; } 12 | 13 | public virtual int Routeint { get; set; } 14 | 15 | public virtual int EventId { get; set; } 16 | 17 | public virtual int Rate { get; set; } 18 | 19 | public virtual int StatusCount { get; set; } 20 | 21 | public virtual bool IsValid { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/UserMusic.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class UserMusic 4 | { 5 | public virtual int MusicId { get; set; } 6 | 7 | public virtual int Level { get; set; } 8 | 9 | public virtual int PlayCount { get; set; } 10 | 11 | public virtual int ScoreMax { get; set; } 12 | 13 | public virtual int ResRequestCount { get; set; } 14 | 15 | public virtual int ResAcceptCount { get; set; } 16 | 17 | public virtual int ResSuccessCount { get; set; } 18 | 19 | public virtual int MissCount { get; set; } 20 | 21 | public virtual int MaxComboCount { get; set; } 22 | 23 | public virtual bool IsFullCombo { get; set; } 24 | 25 | public virtual bool IsAllJustice { get; set; } 26 | 27 | public virtual bool IsSuccess { get; set; } 28 | 29 | public virtual int FullChain { get; set; } 30 | 31 | public virtual int MaxChain { get; set; } 32 | 33 | public virtual int ScoreRank { get; set; } 34 | 35 | public virtual bool IsLock { get; set; } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/UserPlayLog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MiniMe.Chunithm.Protocols 4 | { 5 | public class UserPlayLog 6 | { 7 | public virtual int OrderId { get; set; } 8 | 9 | public virtual int SortNumber { get; set; } 10 | 11 | public virtual int PlaceId { get; set; } 12 | 13 | public virtual DateTimeOffset PlayDate { get; set; } 14 | 15 | public virtual DateTimeOffset UserPlayDate { get; set; } 16 | 17 | public virtual int MusicId { get; set; } 18 | 19 | public virtual int Level { get; set; } 20 | 21 | public virtual int CustomId { get; set; } 22 | 23 | public virtual int PlayedUserId1 { get; set; } 24 | 25 | public virtual int PlayedUserId2 { get; set; } 26 | 27 | public virtual int PlayedUserId3 { get; set; } 28 | 29 | public virtual string PlayedUserName1 { get; set; } 30 | 31 | public virtual string PlayedUserName2 { get; set; } 32 | 33 | public virtual string PlayedUserName3 { get; set; } 34 | 35 | public virtual int PlayedMusicLevel1 { get; set; } 36 | 37 | public virtual int PlayedMusicLevel2 { get; set; } 38 | 39 | public virtual int PlayedMusicLevel3 { get; set; } 40 | 41 | public virtual int PlayedCustom1 { get; set; } 42 | 43 | public virtual int PlayedCustom2 { get; set; } 44 | 45 | public virtual int PlayedCustom3 { get; set; } 46 | 47 | public virtual int Track { get; set; } 48 | 49 | public virtual int Score { get; set; } 50 | 51 | public virtual int Rank { get; set; } 52 | 53 | public virtual int MaxCombo { get; set; } 54 | 55 | public virtual int MaxChain { get; set; } 56 | 57 | public virtual int RateTap { get; set; } 58 | 59 | public virtual int RateHold { get; set; } 60 | 61 | public virtual int RateSlide { get; set; } 62 | 63 | public virtual int RateAir { get; set; } 64 | 65 | public virtual int RateFlick { get; set; } 66 | 67 | public virtual int JudgeGuilty { get; set; } 68 | 69 | public virtual int JudgeAttack { get; set; } 70 | 71 | public virtual int JudgeJustice { get; set; } 72 | 73 | public virtual int JudgeCritical { get; set; } 74 | 75 | public virtual int EventId { get; set; } 76 | 77 | public virtual int PlayerRating { get; set; } 78 | 79 | public virtual bool IsNewRecord { get; set; } 80 | 81 | public virtual bool IsFullCombo { get; set; } 82 | 83 | public virtual int FullChainKind { get; set; } 84 | 85 | public virtual bool IsAllJustice { get; set; } 86 | 87 | public virtual bool IsContinue { get; set; } 88 | 89 | public virtual bool IsFreeToPlay { get; set; } 90 | 91 | public virtual int CharacterId { get; set; } 92 | 93 | public virtual int SkillId { get; set; } 94 | 95 | public virtual int PlayKind { get; set; } 96 | 97 | public virtual bool IsClear { get; set; } 98 | 99 | public virtual int SkillLevel { get; set; } 100 | 101 | public virtual int SkillEffect { get; set; } 102 | 103 | public virtual string PlaceName { get; set; } 104 | 105 | public virtual bool IsMaimai { get; set; } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/UserProfile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MiniMe.Chunithm.Protocols 4 | { 5 | public class UserProfile 6 | { 7 | // NFC LUID 8 | public virtual string AccessCode { get; set; } 9 | 10 | // Uses wide latin chars 11 | public virtual string UserName { get; set; } 12 | 13 | public virtual bool IsWebJoin { get; set; } 14 | 15 | public virtual DateTimeOffset WebLimitDate { get; set; } 16 | 17 | public virtual int Level { get; set; } 18 | 19 | public virtual int ReincarnationNum { get; set; } 20 | 21 | public virtual int Exp { get; set; } 22 | 23 | public virtual int Point { get; set; } 24 | 25 | public virtual long TotalPoint { get; set; } 26 | 27 | public virtual int PlayCount { get; set; } 28 | 29 | public virtual int MultiPlayCount { get; set; } 30 | 31 | public virtual int MultiWinCount { get; set; } 32 | 33 | public virtual int RequestResCount { get; set; } 34 | 35 | public virtual int AcceptResCount { get; set; } 36 | 37 | public virtual int SuccessResCount { get; set; } 38 | 39 | public virtual int PlayerRating { get; set; } 40 | 41 | public virtual int HighestRating { get; set; } 42 | 43 | public virtual int NameplateId { get; set; } 44 | 45 | public virtual int FrameId { get; set; } 46 | 47 | public virtual int CharacterId { get; set; } 48 | 49 | public virtual int TrophyId { get; set; } 50 | 51 | public virtual int PlayedTutorialBit { get; set; } 52 | 53 | public virtual int FirstTutorialCancelNum { get; set; } 54 | 55 | public virtual int MasterTutorialCancelNum { get; set; } 56 | 57 | public virtual int TotalRepertoireCount { get; set; } 58 | 59 | public virtual int TotalMapNum { get; set; } 60 | 61 | public virtual long TotalHiScore { get; set; } 62 | 63 | public virtual long TotalBasicHighScore { get; set; } 64 | 65 | public virtual long TotalAdvancedHighScore { get; set; } 66 | 67 | public virtual long TotalExpertHighScore { get; set; } 68 | 69 | public virtual long TotalMasterHighScore { get; set; } 70 | 71 | public virtual DateTimeOffset EventWatchedDate { get; set; } 72 | 73 | public virtual int FriendCount { get; set; } 74 | 75 | public virtual bool IsMaimai { get; set; } 76 | 77 | public virtual string FirstGameId { get; set; } 78 | 79 | public virtual string FirstRomVersion { get; set; } 80 | 81 | public virtual string FirstDataVersion { get; set; } 82 | 83 | public virtual DateTimeOffset FirstPlayDate { get; set; } 84 | 85 | public virtual string LastGameId { get; set; } 86 | 87 | public virtual string LastRomVersion { get; set; } 88 | 89 | public virtual string LastDataVersion { get; set; } 90 | 91 | public virtual DateTimeOffset LastPlayDate { get; set; } 92 | 93 | // ALLNet place ID 94 | public virtual int LastPlaceId { get; set; } 95 | 96 | // ALLNet place name 97 | public virtual string LastPlaceName { get; set; } 98 | 99 | // ALLNet "region0" 100 | public virtual string LastRegionId { get; set; } 101 | 102 | // ALLNet "region_name0" 103 | public virtual string LastRegionName { get; set; } 104 | 105 | // ALLNet "allnet_id" 106 | public virtual string LastAllNetId { get; set; } 107 | 108 | // Keychip ID 109 | public virtual string LastClientId { get; set; } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/UserRecentRating.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Chunithm.Protocols 2 | { 3 | public class UserRecentRating 4 | { 5 | public int MusicId { get; set; } 6 | 7 | public int DifficultId { get; set; } 8 | 9 | public int RomVersionCode { get; set; } 10 | 11 | public int Score { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /MiniMe.Chunithm/Protocols/UserRegion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MiniMe.Chunithm.Protocols 4 | { 5 | public class UserRegion 6 | { 7 | public int RegionId { get; set; } 8 | 9 | public int PlayCount { get; set; } 10 | 11 | public DateTimeOffset Created { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /MiniMe.Core/AspNetCore/Extensions/ConfigurationExtension.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | 3 | namespace MiniMe.Core.AspNetCore.Extensions 4 | { 5 | public static class ConfigurationExtension 6 | { 7 | public static TOptions GetOptions(this IConfiguration configuration, string name) 8 | where TOptions : class, new() 9 | { 10 | var options = new TOptions(); 11 | configuration.GetSection(name).Bind(options); 12 | 13 | return options; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /MiniMe.Core/AspNetCore/Hosting/HostServerBase.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Threading; 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.AspNetCore.Routing; 5 | using Microsoft.AspNetCore.Server.Kestrel.Core; 6 | using Microsoft.Extensions.Hosting; 7 | using Serilog; 8 | 9 | namespace MiniMe.Core.AspNetCore.Hosting 10 | { 11 | public abstract class HostServerBase : ServerBase where TStartup : HostStartupBase 12 | { 13 | private CancellationTokenSource _cancellationTokenSource; 14 | 15 | protected HostServerBase(IPEndPoint endPoint) : base(endPoint) 16 | { 17 | } 18 | 19 | public override void Start() 20 | { 21 | OnInitialize(); 22 | 23 | _cancellationTokenSource = new CancellationTokenSource(); 24 | 25 | var host = Host.CreateDefaultBuilder() 26 | .ConfigureWebHostDefaults(ConfigureWebHostDefaults) 27 | .UseSerilog(Logger) 28 | .Build(); 29 | 30 | host.Start(); 31 | 32 | Logger.Information("Now listening on: {endPoint}", EndPoint); 33 | 34 | host.WaitForShutdownAsync(_cancellationTokenSource.Token); 35 | 36 | OnShutdown(); 37 | } 38 | 39 | public override void Stop() 40 | { 41 | _cancellationTokenSource?.Cancel(); 42 | _cancellationTokenSource = null; 43 | } 44 | 45 | protected virtual void OnInitialize() 46 | { 47 | } 48 | 49 | protected virtual void OnShutdown() 50 | { 51 | } 52 | 53 | protected virtual void ConfigureWebHostDefaults(IWebHostBuilder webBuilder) 54 | { 55 | webBuilder 56 | .UseKestrel(o => 57 | { 58 | o.AddServerHeader = false; 59 | ConfigureKestrel(o); 60 | }) 61 | .UseStartup(); 62 | } 63 | 64 | protected virtual void ConfigureKestrel(KestrelServerOptions options) 65 | { 66 | options.Listen(EndPoint); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /MiniMe.Core/AspNetCore/Hosting/HostStartupBase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using Microsoft.Extensions.Hosting; 5 | using MiniMe.Core.AspNetCore.Middleswares; 6 | 7 | namespace MiniMe.Core.AspNetCore.Hosting 8 | { 9 | public abstract class HostStartupBase 10 | { 11 | public virtual void Configure(IApplicationBuilder app) 12 | { 13 | app.UseRouting(); 14 | app.UseMiddleware(); 15 | 16 | app.UseEndpoints(endpoints => 17 | { 18 | endpoints.MapControllers(); 19 | }); 20 | } 21 | 22 | public virtual void ConfigureServices(IServiceCollection services) 23 | { 24 | services 25 | .Configure(o => o.SuppressStatusMessages = true) 26 | .AddControllers(ConfigureControllers) 27 | .AddNewtonsoftJson(ConfigureJson); 28 | } 29 | 30 | protected virtual void ConfigureControllers(MvcOptions options) 31 | { 32 | } 33 | 34 | protected virtual void ConfigureJson(MvcNewtonsoftJsonOptions options) 35 | { 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /MiniMe.Core/AspNetCore/Middleswares/BodyBufferingMiddleware.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.AspNetCore.Http; 3 | 4 | namespace MiniMe.Core.AspNetCore.Middleswares 5 | { 6 | public sealed class BodyBufferingMiddleware : MiddlewareBase 7 | { 8 | public BodyBufferingMiddleware(RequestDelegate next) : base(next) 9 | { 10 | } 11 | 12 | protected override Task BeforeInvoke(HttpContext context) 13 | { 14 | context.Request.EnableBuffering(); 15 | 16 | return Task.CompletedTask; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /MiniMe.Core/AspNetCore/Middleswares/MiddlewareBase.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.AspNetCore.Http; 3 | 4 | namespace MiniMe.Core.AspNetCore.Middleswares 5 | { 6 | public abstract class MiddlewareBase 7 | { 8 | private readonly RequestDelegate _next; 9 | 10 | protected MiddlewareBase(RequestDelegate next) 11 | { 12 | _next = next; 13 | } 14 | 15 | public virtual async Task Invoke(HttpContext context) 16 | { 17 | await BeforeInvoke(context); 18 | await Next(context); 19 | await AfterInvoke(context); 20 | } 21 | 22 | protected async Task Next(HttpContext context) 23 | { 24 | await _next(context); 25 | } 26 | 27 | protected virtual Task BeforeInvoke(HttpContext context) 28 | { 29 | return Task.CompletedTask; 30 | } 31 | 32 | protected virtual Task AfterInvoke(HttpContext context) 33 | { 34 | return Task.CompletedTask; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /MiniMe.Core/AspNetCore/Mvc/Formatters/FormInputFormatter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Net.Mime; 6 | using System.Text; 7 | using System.Text.RegularExpressions; 8 | using System.Threading.Tasks; 9 | using Microsoft.AspNetCore.Mvc.Formatters; 10 | using Newtonsoft.Json.Linq; 11 | using Serilog; 12 | 13 | namespace MiniMe.Core.AspNetCore.Mvc.Formatters 14 | { 15 | public class FormInputFormatter : TextInputFormatter 16 | { 17 | private readonly bool _ignoreContentType; 18 | 19 | public FormInputFormatter(bool ignoreContentType = false) 20 | { 21 | _ignoreContentType = ignoreContentType; 22 | 23 | SupportedMediaTypes.Add(MediaTypeNames.Text.Plain); 24 | SupportedMediaTypes.Add("application/x-www-form-urlencoded"); 25 | SupportedEncodings.Add(UTF8EncodingWithoutBOM); 26 | SupportedEncodings.Add(UTF16EncodingLittleEndian); 27 | } 28 | 29 | public override bool CanRead(InputFormatterContext context) 30 | { 31 | return _ignoreContentType || base.CanRead(context); 32 | } 33 | 34 | public override async Task ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding) 35 | { 36 | if (context == null) 37 | { 38 | throw new ArgumentNullException(nameof(context)); 39 | } 40 | 41 | if (encoding == null) 42 | { 43 | throw new ArgumentNullException(nameof(encoding)); 44 | } 45 | 46 | try 47 | { 48 | using var reader = new StreamReader(context.HttpContext.Request.Body, encoding); 49 | var value = await reader.ReadToEndAsync(); 50 | 51 | IEnumerable lines = Regex.Split(value, "[\r\n]+") 52 | .Select(v => v.Trim(' ')) 53 | .Where(v => !string.IsNullOrEmpty(v)); 54 | 55 | JToken result; 56 | 57 | if (context.ModelType.IsArray || typeof(IEnumerable).IsAssignableFrom(context.ModelType)) 58 | { 59 | var array = new JArray(); 60 | 61 | foreach (var obj in lines.Select(Deserialize)) 62 | { 63 | array.Add(obj); 64 | } 65 | 66 | result = array; 67 | } 68 | else 69 | { 70 | result = Deserialize(lines.First()); 71 | } 72 | 73 | return await InputFormatterResult.SuccessAsync(result.ToObject(context.ModelType)); 74 | } 75 | catch (Exception e) 76 | { 77 | Log.Fatal(e, e.Message); 78 | } 79 | 80 | return await InputFormatterResult.FailureAsync(); 81 | } 82 | 83 | private static JObject Deserialize(string formData) 84 | { 85 | var jObj = new JObject(); 86 | 87 | foreach (string[] kv in formData.Split('&').Select(kv => kv.Split('=', 2))) 88 | { 89 | jObj[kv[0]] = kv[1]; 90 | } 91 | 92 | return jObj; 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /MiniMe.Core/AspNetCore/Mvc/Formatters/FormOutputFormatter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net.Mime; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Microsoft.AspNetCore.Http; 8 | using Microsoft.AspNetCore.Mvc.Formatters; 9 | using Microsoft.Extensions.Primitives; 10 | using Newtonsoft.Json.Linq; 11 | 12 | namespace MiniMe.Core.AspNetCore.Mvc.Formatters 13 | { 14 | public class FormOutputFormatter : TextOutputFormatter 15 | { 16 | private readonly bool _ignoreContentType; 17 | 18 | public FormOutputFormatter(bool ignoreContentType = false) 19 | { 20 | _ignoreContentType = ignoreContentType; 21 | 22 | SupportedMediaTypes.Add(MediaTypeNames.Text.Plain); 23 | SupportedMediaTypes.Add("application/x-www-form-urlencoded"); 24 | SupportedEncodings.Add(Encoding.UTF8); 25 | } 26 | 27 | protected override bool CanWriteType(Type type) 28 | { 29 | return !type.IsValueType; 30 | } 31 | 32 | public override bool CanWriteResult(OutputFormatterCanWriteContext context) 33 | { 34 | return _ignoreContentType || context.HttpContext.Request.ContentType == "application/x-www-form-urlencoded"; 35 | } 36 | 37 | public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding) 38 | { 39 | if (context == null) 40 | { 41 | throw new ArgumentNullException(nameof(context)); 42 | } 43 | 44 | if (selectedEncoding == null) 45 | { 46 | throw new ArgumentNullException(nameof(selectedEncoding)); 47 | } 48 | 49 | string result; 50 | 51 | if (context.Object is IEnumerable enumerable) 52 | { 53 | result = string.Join(Environment.NewLine, enumerable.Select(Serialize)); 54 | } 55 | else 56 | { 57 | result = Serialize(context.Object); 58 | } 59 | 60 | result += Environment.NewLine; 61 | 62 | await context.HttpContext.Response.WriteAsync(result, selectedEncoding); 63 | } 64 | 65 | private static string Serialize(object obj) 66 | { 67 | IEnumerable propertyParams = JObject.FromObject(obj) 68 | .Children() 69 | .OfType() 70 | .Select(p => $"{p.Name}={p.Value}"); 71 | 72 | return string.Join("&", propertyParams); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /MiniMe.Core/AspNetCore/RequestDecompression/DeflateDecompressionProviderCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.ObjectModel; 3 | 4 | namespace MiniMe.Core.AspNetCore.RequestDecompression 5 | { 6 | public class DeflateDecompressionProviderCollection : Collection 7 | { 8 | public void Add() where T : IDecompressionProvider 9 | { 10 | Add(Activator.CreateInstance()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /MiniMe.Core/AspNetCore/RequestDecompression/IDecompressionProvider.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using Microsoft.AspNetCore.Http; 3 | 4 | namespace MiniMe.Core.AspNetCore.RequestDecompression 5 | { 6 | public interface IDecompressionProvider 7 | { 8 | Stream CreateStream(Stream inputStream, IHeaderDictionary requestHeaders); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /MiniMe.Core/AspNetCore/RequestDecompression/Providers/Base64DecompressionProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using Microsoft.AspNetCore.Http; 4 | 5 | namespace MiniMe.Core.AspNetCore.RequestDecompression 6 | { 7 | public class Base64DecompressionProvider : RequestDecompressionProvider 8 | { 9 | protected override Stream CreateStream(Stream inputStream, IHeaderDictionary headers) 10 | { 11 | using var reader = new StreamReader(inputStream); 12 | var value = reader.ReadToEnd().Trim('\r', '\n', ' '); 13 | 14 | byte[] binary = Convert.FromBase64String(value); 15 | 16 | return new MemoryStream(binary); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /MiniMe.Core/AspNetCore/RequestDecompression/Providers/DeflateDecompressionProvider.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.IO.Compression; 3 | using Microsoft.AspNetCore.Http; 4 | 5 | namespace MiniMe.Core.AspNetCore.RequestDecompression 6 | { 7 | public class DeflateDecompressionProvider : RequestDecompressionProvider 8 | { 9 | protected override Stream CreateStream(Stream outputStream, IHeaderDictionary headers) 10 | { 11 | return new DeflateStream(outputStream, CompressionMode.Decompress); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /MiniMe.Core/AspNetCore/RequestDecompression/Providers/ZlibDecompressionProvider.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using Ionic.Zlib; 3 | using Microsoft.AspNetCore.Http; 4 | 5 | namespace MiniMe.Core.AspNetCore.RequestDecompression 6 | { 7 | public class ZlibDecompressionProvider : RequestDecompressionProvider 8 | { 9 | protected override Stream CreateStream(Stream inputStream, IHeaderDictionary headers) 10 | { 11 | return new ZlibStream(inputStream, CompressionMode.Decompress); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /MiniMe.Core/AspNetCore/RequestDecompression/RequestDecompressionBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Builder; 3 | 4 | namespace MiniMe.Core.AspNetCore.RequestDecompression 5 | { 6 | public static class RequestDecompressionBuilderExtensions 7 | { 8 | public static IApplicationBuilder UseRequestDecompression(this IApplicationBuilder builder) 9 | { 10 | if (builder == null) 11 | { 12 | throw new ArgumentNullException(nameof(builder)); 13 | } 14 | 15 | return builder.UseMiddleware(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /MiniMe.Core/AspNetCore/RequestDecompression/RequestDecompressionMiddleware.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.AspNetCore.Http.Features; 6 | using Microsoft.Extensions.Options; 7 | 8 | namespace MiniMe.Core.AspNetCore.RequestDecompression 9 | { 10 | public class RequestDecompressionMiddleware : IMiddleware 11 | { 12 | private readonly IDecompressionProvider[] _providers; 13 | 14 | public RequestDecompressionMiddleware(IOptions options) 15 | { 16 | _providers = options.Value.Providers.ToArray(); 17 | } 18 | 19 | public async Task InvokeAsync(HttpContext context, RequestDelegate next) 20 | { 21 | var stream = context.Request.Body; 22 | 23 | // Kestrel server does not support synchronous I/O 24 | var bodyFeature = context.Features.Get(); 25 | var allowSynchronousIO = bodyFeature.AllowSynchronousIO; 26 | bodyFeature.AllowSynchronousIO = true; 27 | 28 | foreach (var provider in _providers) 29 | { 30 | stream = provider.CreateStream(stream, context.Request.Headers); 31 | } 32 | 33 | MemoryStream decoded = default; 34 | 35 | if (stream != context.Request.Body) 36 | { 37 | decoded = new MemoryStream(); 38 | 39 | await stream.CopyToAsync(decoded); 40 | await stream.DisposeAsync(); 41 | 42 | decoded.Position = 0; 43 | context.Request.Body = decoded; 44 | context.Request.ContentLength = decoded.Length; 45 | } 46 | 47 | try 48 | { 49 | await next(context); 50 | } 51 | finally 52 | { 53 | if (decoded != null) 54 | { 55 | await decoded.DisposeAsync(); 56 | } 57 | 58 | bodyFeature.AllowSynchronousIO = allowSynchronousIO; 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /MiniMe.Core/AspNetCore/RequestDecompression/RequestDecompressionOptions.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Core.AspNetCore.RequestDecompression 2 | { 3 | public sealed class RequestDecompressionOptions 4 | { 5 | public DeflateDecompressionProviderCollection Providers { get; } = new DeflateDecompressionProviderCollection(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /MiniMe.Core/AspNetCore/RequestDecompression/RequestDecompressionProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.Net.Http.Headers; 7 | 8 | namespace MiniMe.Core.AspNetCore.RequestDecompression 9 | { 10 | public abstract class RequestDecompressionProvider : IDecompressionProvider 11 | { 12 | public List ContentTypes => _contentTypes ??= new List(); 13 | 14 | public List EncodingNames => _encodingNames ??= new List(); 15 | 16 | private List _contentTypes; 17 | private List _encodingNames; 18 | 19 | Stream IDecompressionProvider.CreateStream(Stream inputStream, IHeaderDictionary requestHeaders) 20 | { 21 | if (_contentTypes?.Count > 0) 22 | { 23 | if (!requestHeaders.TryGetValue(HeaderNames.ContentType, out var contenType)) 24 | { 25 | return inputStream; 26 | } 27 | 28 | if (!_contentTypes.All(v => v.Equals(contenType, StringComparison.OrdinalIgnoreCase))) 29 | { 30 | return inputStream; 31 | } 32 | } 33 | 34 | if (_encodingNames?.Count > 0) 35 | { 36 | if (!requestHeaders.TryGetValue(HeaderNames.ContentEncoding, out var encoding)) 37 | { 38 | return inputStream; 39 | } 40 | 41 | if (!_encodingNames.All(v => v.Equals(encoding, StringComparison.OrdinalIgnoreCase))) 42 | { 43 | return inputStream; 44 | } 45 | } 46 | 47 | return CreateStream(inputStream, requestHeaders); 48 | } 49 | 50 | protected abstract Stream CreateStream(Stream inputStream, IHeaderDictionary requestHeaders); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /MiniMe.Core/AspNetCore/RequestDecompression/RequestDecompressionServicesExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.DependencyInjection.Extensions; 4 | 5 | namespace MiniMe.Core.AspNetCore.RequestDecompression 6 | { 7 | public static class RequestDecompressionServicesExtensions 8 | { 9 | public static IServiceCollection AddRequestDecompression(this IServiceCollection services, Action configureOptions) 10 | { 11 | services.Configure(configureOptions); 12 | services.TryAddSingleton(); 13 | 14 | return services; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MiniMe.Core/AspNetCore/ResponseCompression/ZlibCompressionProvider.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using Ionic.Zlib; 3 | using Microsoft.AspNetCore.ResponseCompression; 4 | 5 | namespace MiniMe.Core.AspNetCore.ResponseCompression 6 | { 7 | public class ZlibCompressionProvider : ICompressionProvider 8 | { 9 | public string EncodingName => "deflate"; 10 | 11 | public bool SupportsFlush => true; 12 | 13 | public Stream CreateStream(Stream outputStream) 14 | { 15 | return new ZlibStream(outputStream, CompressionMode.Compress); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /MiniMe.Core/Extension/ILGeneratorExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Reflection.Emit; 4 | 5 | namespace MiniMe.Core.Extensions 6 | { 7 | internal static class ILGeneratorExtension 8 | { 9 | public static void EmitBox(this ILGenerator generator, Type type) 10 | { 11 | generator.Emit(OpCodes.Box, type); 12 | } 13 | 14 | public static void EmitUnbox(this ILGenerator generator, Type type) 15 | { 16 | if (type.IsValueType) 17 | generator.Emit(OpCodes.Unbox_Any, type); 18 | else 19 | generator.Emit(OpCodes.Castclass, type); 20 | } 21 | 22 | public static void EmitCall(this ILGenerator generator, MethodInfo methodInfo) 23 | { 24 | if (methodInfo.DeclaringType.IsValueType) 25 | generator.Emit(OpCodes.Call, methodInfo); 26 | else 27 | generator.Emit(OpCodes.Callvirt, methodInfo); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /MiniMe.Core/Extension/ReflectionExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Reflection.Emit; 4 | using MiniMe.Core.Utilities; 5 | 6 | namespace MiniMe.Core.Extensions 7 | { 8 | internal static class ReflectionExtension 9 | { 10 | public static TDelegate CreateDelegate(this DynamicMethod method) where TDelegate : Delegate 11 | { 12 | return (TDelegate)method.CreateDelegate(typeof(TDelegate)); 13 | } 14 | 15 | public static FieldInfo GetBackingField(this PropertyInfo propertyInfo) 16 | { 17 | var fieldName = $"<{propertyInfo.Name}>k__BackingField"; 18 | return propertyInfo.DeclaringType!.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance); 19 | } 20 | 21 | public static object GetMemberValue(this MemberInfo memberInfo, object target) 22 | { 23 | Validation.ArgumentNotNull(memberInfo, nameof(memberInfo)); 24 | Validation.ArgumentNotNull(target, nameof(target)); 25 | 26 | switch (memberInfo) 27 | { 28 | case PropertyInfo propertyInfo: 29 | return propertyInfo.GetValue(target); 30 | 31 | case FieldInfo fieldInfo: 32 | return fieldInfo.GetValue(target); 33 | 34 | default: 35 | throw new ArgumentException($"MemberInfo '{nameof(memberInfo)}' must be of type FieldInfo or PropertyInfo"); 36 | } 37 | } 38 | 39 | public static void SetMemberValue(this MemberInfo memberInfo, object target, object value) 40 | { 41 | Validation.ArgumentNotNull(memberInfo, nameof(memberInfo)); 42 | Validation.ArgumentNotNull(target, nameof(target)); 43 | 44 | switch (memberInfo) 45 | { 46 | case PropertyInfo propertyInfo: 47 | propertyInfo.SetValue(target, value); 48 | break; 49 | 50 | case FieldInfo fieldInfo: 51 | fieldInfo.SetValue(target, value); 52 | break; 53 | 54 | default: 55 | throw new ArgumentException($"MemberInfo '{nameof(memberInfo)}' must be of type FieldInfo or PropertyInfo"); 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /MiniMe.Core/Extension/SpanExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace MiniMe.Core.Extension 6 | { 7 | public static class SpanExtension 8 | { 9 | public static void Write(this Span span, T[] value, int offset = 0) 10 | { 11 | value.CopyTo(span.Slice(offset)); 12 | } 13 | 14 | public static void Write(this Span span, TTo value, int offset = 0) 15 | { 16 | Unsafe.As(ref span[offset]) = value; 17 | } 18 | 19 | public static T Read(this Span span, int offset = 0) 20 | { 21 | return Read((ReadOnlySpan)span, offset); 22 | } 23 | 24 | public static T Read(this ReadOnlySpan span, int offset = 0) 25 | { 26 | int size = Marshal.SizeOf(); 27 | return Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(span.Slice(offset, size))); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /MiniMe.Core/IO/ByteBuffer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.CompilerServices; 3 | 4 | namespace MiniMe.Core.IO 5 | { 6 | public unsafe class ByteBuffer 7 | { 8 | public byte[] Data => _data; 9 | 10 | public int Length => Data.Length; 11 | 12 | private byte[] _data; 13 | 14 | public ByteBuffer(int capacity) : this(new byte[capacity]) 15 | { 16 | } 17 | 18 | public ByteBuffer(byte[] data) 19 | { 20 | _data = data; 21 | } 22 | 23 | public void Resize(int capacity) 24 | { 25 | var destination = new byte[capacity]; 26 | 27 | fixed (byte* pSource = _data) 28 | fixed (byte* pDestination = destination) 29 | { 30 | int size = Math.Min(capacity, _data.Length); 31 | Buffer.MemoryCopy(pSource, pDestination, size, size); 32 | } 33 | 34 | _data = destination; 35 | } 36 | 37 | public ReadOnlySpan AsSpan() => AsSpan(0, _data.Length); 38 | 39 | public ReadOnlySpan AsSpan(int length) => AsSpan(0, length); 40 | 41 | public ReadOnlySpan AsSpan(int start, int length) 42 | { 43 | return new ReadOnlySpan(_data, start, length); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MiniMe.Core/LoggerNameAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MiniMe.Core 4 | { 5 | [AttributeUsage(AttributeTargets.Class)] 6 | public class LoggerNameAttribute : Attribute 7 | { 8 | public string Name { get; } 9 | 10 | public LoggerNameAttribute(string name) 11 | { 12 | Name = name; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MiniMe.Core/Mapper/DynamicAccessor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Reflection.Emit; 4 | using MiniMe.Core.Extensions; 5 | 6 | namespace MiniMe.Core.Mapper 7 | { 8 | internal static class DynamicAccessor 9 | { 10 | public delegate object Getter(object obj); 11 | public delegate void Setter(object obj, object value); 12 | public delegate object Constructor(); 13 | 14 | public static Constructor CreateConstructor(Type type) 15 | { 16 | var constructorInfo = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); 17 | 18 | if (type.IsAbstract) 19 | return null; 20 | 21 | if (constructorInfo == null && !type.IsValueType) 22 | return null; 23 | 24 | var method = new DynamicMethod( 25 | ConstructorInfo.ConstructorName, 26 | typeof(object), 27 | Type.EmptyTypes, 28 | typeof(DynamicAccessor).Module, 29 | true); 30 | 31 | var ilGenerator = method.GetILGenerator(); 32 | 33 | if (constructorInfo == null) 34 | { 35 | var local = ilGenerator.DeclareLocal(type); 36 | ilGenerator.Emit(OpCodes.Ldloca_S, local); 37 | ilGenerator.Emit(OpCodes.Initobj, type); 38 | ilGenerator.Emit(OpCodes.Ldloc, local); 39 | ilGenerator.Emit(OpCodes.Box, type); 40 | } 41 | else 42 | { 43 | ilGenerator.Emit(OpCodes.Newobj, constructorInfo); 44 | } 45 | 46 | ilGenerator.Emit(OpCodes.Ret); 47 | 48 | return method.CreateDelegate(); 49 | } 50 | 51 | public static Getter CreateMemberGetter(MemberInfo memberInfo) 52 | { 53 | if (memberInfo is PropertyInfo propertyInfo) 54 | return CreatePropertyGetter(propertyInfo); 55 | 56 | if (memberInfo is FieldInfo fieldInfo) 57 | return CreateFieldGetter(fieldInfo); 58 | 59 | throw new ArgumentException($"MemberInfo '{nameof(memberInfo)}' must be of type FieldInfo or PropertyInfo"); 60 | } 61 | 62 | public static Setter CreateMemberSetter(MemberInfo memberInfo) 63 | { 64 | if (memberInfo is PropertyInfo propertyInfo) 65 | return CreatePropertySetter(propertyInfo); 66 | 67 | if (memberInfo is FieldInfo fieldInfo) 68 | return CreateFieldSetter(fieldInfo); 69 | 70 | throw new ArgumentException($"MemberInfo '{nameof(memberInfo)}' must be of type FieldInfo or PropertyInfo"); 71 | } 72 | 73 | public static Getter CreateFieldGetter(FieldInfo fieldInfo) 74 | { 75 | if (!fieldInfo.IsPublic) 76 | return null; 77 | 78 | var method = CreateGetterMethod(fieldInfo.Name); 79 | var ilGenerator = method.GetILGenerator(); 80 | 81 | ilGenerator.Emit(OpCodes.Ldarg_0); 82 | ilGenerator.EmitUnbox(fieldInfo.DeclaringType); 83 | ilGenerator.Emit(OpCodes.Ldfld, fieldInfo); 84 | ilGenerator.EmitBox(fieldInfo.FieldType); 85 | ilGenerator.Emit(OpCodes.Ret); 86 | 87 | return method.CreateDelegate(); 88 | } 89 | 90 | public static Setter CreateFieldSetter(FieldInfo fieldInfo) 91 | { 92 | if (!fieldInfo.IsPublic) 93 | return null; 94 | 95 | var method = CreateSetterMethod(fieldInfo.Name); 96 | var ilGenerator = method.GetILGenerator(); 97 | 98 | ilGenerator.Emit(OpCodes.Ldarg_0); 99 | ilGenerator.EmitUnbox(fieldInfo.DeclaringType); 100 | ilGenerator.Emit(OpCodes.Ldarg_1); 101 | ilGenerator.EmitUnbox(fieldInfo.FieldType); 102 | ilGenerator.Emit(OpCodes.Stfld, fieldInfo); 103 | ilGenerator.Emit(OpCodes.Ret); 104 | 105 | return method.CreateDelegate(); 106 | } 107 | 108 | public static Getter CreatePropertyGetter(PropertyInfo propertyInfo) 109 | { 110 | if (propertyInfo.GetMethod?.IsPublic != true) 111 | return null; 112 | 113 | var method = CreateGetterMethod(propertyInfo.GetMethod.Name); 114 | var ilGenerator = method.GetILGenerator(); 115 | 116 | ilGenerator.Emit(OpCodes.Ldarg_0); 117 | ilGenerator.EmitUnbox(propertyInfo.DeclaringType); 118 | ilGenerator.EmitCall(propertyInfo.GetMethod); 119 | ilGenerator.EmitBox(propertyInfo.PropertyType); 120 | ilGenerator.Emit(OpCodes.Ret); 121 | 122 | return method.CreateDelegate(); 123 | } 124 | 125 | public static Setter CreatePropertySetter(PropertyInfo propertyInfo) 126 | { 127 | if (propertyInfo.SetMethod?.IsPublic != true) 128 | return null; 129 | 130 | var method = CreateSetterMethod(propertyInfo.SetMethod.Name); 131 | var ilGenerator = method.GetILGenerator(); 132 | 133 | ilGenerator.Emit(OpCodes.Ldarg_0); 134 | ilGenerator.EmitUnbox(propertyInfo.DeclaringType); 135 | ilGenerator.Emit(OpCodes.Ldarg_1); 136 | ilGenerator.EmitUnbox(propertyInfo.PropertyType); 137 | ilGenerator.EmitCall(propertyInfo.SetMethod); 138 | ilGenerator.Emit(OpCodes.Ret); 139 | 140 | return method.CreateDelegate(); 141 | } 142 | 143 | private static DynamicMethod CreateGetterMethod(string name) 144 | { 145 | return new DynamicMethod( 146 | name, 147 | typeof(object), 148 | new[] { typeof(object) }, 149 | typeof(DynamicAccessor).Module, 150 | true); 151 | } 152 | 153 | private static DynamicMethod CreateSetterMethod(string name) 154 | { 155 | return new DynamicMethod( 156 | name, 157 | typeof(void), 158 | new[] { typeof(object), typeof(object) }, 159 | typeof(DynamicAccessor).Module, 160 | true); 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /MiniMe.Core/Mapper/ObjectMapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using System.Diagnostics.CodeAnalysis; 5 | using System.Linq; 6 | using System.Reflection; 7 | 8 | namespace MiniMe.Core.Mapper 9 | { 10 | public static class ObjectMapper 11 | { 12 | private static readonly ConcurrentDictionary _contracts = 13 | new ConcurrentDictionary(); 14 | 15 | private static readonly ConcurrentDictionary _mappingTables = 16 | new ConcurrentDictionary(); 17 | 18 | private static readonly MethodInfo _mapGenericMethod; 19 | 20 | static ObjectMapper() 21 | { 22 | _mapGenericMethod = typeof(ObjectMapper).GetMethods() 23 | .Single(m => m.IsGenericMethod && m.GetGenericArguments().Length == 2); 24 | } 25 | 26 | public static IEnumerable Map([NotNull] IEnumerable source) where T : class, new() 27 | { 28 | if (source == null) 29 | return Enumerable.Empty(); 30 | 31 | return source.Select(Map); 32 | } 33 | 34 | public static T Map(object source) where T : class, new() 35 | { 36 | if (source == null) 37 | { 38 | return null; 39 | } 40 | 41 | var destination = new T(); 42 | 43 | var method = _mapGenericMethod.MakeGenericMethod(source.GetType(), typeof(T)); 44 | method.Invoke(null, new[] { source, destination }); 45 | 46 | return destination; 47 | } 48 | 49 | public static void Map([NotNull] TSource source, [NotNull] TDestination destination) 50 | { 51 | if (typeof(TSource) == typeof(TDestination)) 52 | { 53 | foreach (var provider in GetProviders()) 54 | { 55 | var value = provider.Get(source); 56 | provider.Set(destination, value); 57 | } 58 | } 59 | else 60 | { 61 | foreach (var map in GetMappings()) 62 | { 63 | var value = map.Source.Get(source); 64 | map.Destination.Set(destination, value); 65 | } 66 | } 67 | } 68 | 69 | private static IEnumerable GetMappings() 70 | { 71 | var direction = new MappingDirection(typeof(TSource), typeof(TDestination)); 72 | 73 | if (!_mappingTables.TryGetValue(direction, out PropertyMap[] mappings)) 74 | { 75 | Dictionary srcProviders = GetProviders().ToDictionary(p => p.Name); 76 | Dictionary dstProviders = GetProviders().ToDictionary(p => p.Name); 77 | 78 | IEnumerable<(string, Type)> srcPivots = srcProviders.Values.Select(p => (p.Name, p.PropertyType)); 79 | IEnumerable<(string, Type)> dstPivots = dstProviders.Values.Select(p => (p.Name, p.PropertyType)); 80 | 81 | mappings = srcPivots 82 | .Intersect(dstPivots) 83 | .Select(p => new PropertyMap(srcProviders[p.Item1], dstProviders[p.Item1])) 84 | .ToArray(); 85 | 86 | _mappingTables[direction] = mappings; 87 | } 88 | 89 | return mappings; 90 | } 91 | 92 | private static IEnumerable GetProviders() 93 | { 94 | var type = typeof(T); 95 | 96 | if (!_contracts.TryGetValue(type, out PropertyProvider[] contract)) 97 | { 98 | contract = type.GetProperties() 99 | .Where(p => (p.GetMethod?.IsPublic ?? false) && (p.SetMethod?.IsPublic ?? false)) 100 | .Select(p => new PropertyProvider(p)) 101 | .ToArray(); 102 | 103 | _contracts[type] = contract; 104 | } 105 | 106 | return contract; 107 | } 108 | 109 | private readonly struct MappingDirection 110 | { 111 | public Guid Source { get; } 112 | 113 | public Guid Destination { get; } 114 | 115 | public MappingDirection(Type source, Type destination) 116 | { 117 | Source = source.GUID; 118 | Destination = destination.GUID; 119 | } 120 | } 121 | 122 | private readonly struct PropertyProvider 123 | { 124 | public string Name { get; } 125 | 126 | public Type PropertyType { get; } 127 | 128 | public DynamicAccessor.Getter Get { get; } 129 | 130 | public DynamicAccessor.Setter Set { get; } 131 | 132 | public PropertyProvider(PropertyInfo propertyInfo) 133 | { 134 | Name = propertyInfo.Name; 135 | PropertyType = propertyInfo.PropertyType; 136 | Get = DynamicAccessor.CreatePropertyGetter(propertyInfo); 137 | Set = DynamicAccessor.CreatePropertySetter(propertyInfo); 138 | } 139 | } 140 | 141 | private readonly struct PropertyMap 142 | { 143 | public PropertyProvider Source { get; } 144 | 145 | public PropertyProvider Destination { get; } 146 | 147 | public PropertyMap(PropertyProvider source, PropertyProvider destination) 148 | { 149 | Source = source; 150 | Destination = destination; 151 | } 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /MiniMe.Core/MiniMe.Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | MiniMe.Common 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /MiniMe.Core/MiniMeEnvironment.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Reflection; 3 | 4 | namespace MiniMe.Core 5 | { 6 | public static class MiniMeEnvironment 7 | { 8 | public static string DataDirectory { get; } 9 | 10 | static MiniMeEnvironment() 11 | { 12 | var assesmblyDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly()!.Location); 13 | 14 | DataDirectory = Path.Combine(assesmblyDirectory!, "Data"); 15 | 16 | if (!Directory.Exists(DataDirectory)) 17 | { 18 | Directory.CreateDirectory(DataDirectory); 19 | } 20 | } 21 | 22 | public static string GetDataFile(string file) 23 | { 24 | return Path.Combine(DataDirectory, file); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /MiniMe.Core/MiniMeService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | 4 | namespace MiniMe.Core 5 | { 6 | public static class MiniMeService 7 | { 8 | private static readonly ConcurrentDictionary _services = new ConcurrentDictionary(); 9 | 10 | public static void Add(T service) 11 | { 12 | if (_services.ContainsKey(typeof(T))) 13 | return; 14 | 15 | _services.TryAdd(typeof(T), service); 16 | } 17 | 18 | public static T Remove() 19 | { 20 | if (_services.TryRemove(typeof(T), out var service)) 21 | { 22 | return (T)service; 23 | } 24 | 25 | return default; 26 | } 27 | 28 | public static T Get() 29 | { 30 | if (_services.TryGetValue(typeof(T), out var service)) 31 | return (T)service; 32 | 33 | return default; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /MiniMe.Core/Models/IdzPorts.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Core.Models 2 | { 3 | public class IdzPorts 4 | { 5 | public PortSet UserDb { get; set; } 6 | 7 | public PortSet Match { get; set; } 8 | 9 | public PortSet TagMatch { get; set; } 10 | 11 | public int Event { get; set; } 12 | 13 | public int ScreenShot { get; set; } 14 | 15 | public int Echo1 { get; set; } 16 | 17 | public int Echo2 { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /MiniMe.Core/Models/MiniMePorts.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Core.Models 2 | { 3 | public class MiniMePorts 4 | { 5 | public int Aime { get; set; } 6 | 7 | public int AllNet { get; set; } 8 | 9 | public int Billing { get; set; } 10 | 11 | public int Chunithm { get; set; } 12 | 13 | public int Diva { get; set; } 14 | 15 | public IdzPorts Idz { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MiniMe.Core/Models/PortSet.cs: -------------------------------------------------------------------------------- 1 | namespace MiniMe.Core.Models 2 | { 3 | public class PortSet 4 | { 5 | public int? Http { get; set; } 6 | 7 | public int? Tcp { get; set; } 8 | 9 | public int? UdpSend { get; set; } 10 | 11 | public int? UdpRecv { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /MiniMe.Core/Net/TcpServer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Net; 4 | using System.Net.Sockets; 5 | using System.Threading; 6 | 7 | namespace MiniMe.Core.Net 8 | { 9 | public abstract class TcpServer : ServerBase 10 | where TSession : TcpSession 11 | { 12 | public bool IsAlive => _socket != null && !(_socket.Poll(1, SelectMode.SelectRead) && _socket.Available == 0); 13 | 14 | private Socket _socket; 15 | private SocketAsyncEventArgs _socketEventArg; 16 | private bool _stop; 17 | 18 | private readonly ConcurrentDictionary _sessions = new ConcurrentDictionary(); 19 | 20 | protected TcpServer(IPEndPoint endPoint) : base(endPoint) 21 | { 22 | } 23 | 24 | public override void Start() 25 | { 26 | if (_socket != null) 27 | throw new InvalidOperationException(); 28 | 29 | OnInitialize(); 30 | 31 | _socketEventArg = new SocketAsyncEventArgs(); 32 | _socketEventArg.Completed += OnAsyncCompleted; 33 | 34 | _socket = new Socket(EndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); 35 | _socket.Bind(EndPoint); 36 | _socket.Listen(1024); 37 | 38 | Logger.Information("Now listening on: {endPoint}", EndPoint); 39 | OnListen(); 40 | 41 | NextAccept(_socketEventArg); 42 | 43 | while (!_stop && IsAlive) 44 | { 45 | Thread.Sleep(1000); 46 | } 47 | 48 | EnsureShutdown(); 49 | } 50 | 51 | public override void Stop() 52 | { 53 | _stop = true; 54 | } 55 | 56 | private void EnsureShutdown() 57 | { 58 | try 59 | { 60 | _socket.Shutdown(SocketShutdown.Both); 61 | _socket.Dispose(); 62 | _socket = null; 63 | } 64 | catch (Exception) 65 | { 66 | // ignored 67 | } 68 | 69 | OnShutdown(); 70 | } 71 | 72 | private void OnAsyncCompleted(object sender, SocketAsyncEventArgs e) 73 | { 74 | Accept(e); 75 | } 76 | 77 | private void NextAccept(SocketAsyncEventArgs e) 78 | { 79 | e.AcceptSocket = null; 80 | 81 | if (!_socket.AcceptAsync(e)) 82 | Accept(e); 83 | } 84 | 85 | private void Accept(SocketAsyncEventArgs e) 86 | { 87 | if (e.SocketError == SocketError.Success) 88 | { 89 | var session = CreateSession(); 90 | 91 | session.Connect(e.AcceptSocket); 92 | session.Disconnected += SessionOnDisconnected; 93 | 94 | RegisterSession(session); 95 | 96 | Logger.Information("{id} Session opened.", session.Id); 97 | OnSessionOpened(session); 98 | 99 | session.StartReceive(); 100 | } 101 | 102 | NextAccept(e); 103 | } 104 | 105 | private void SessionOnDisconnected(object sender, EventArgs e) 106 | { 107 | if (sender is TSession session) 108 | { 109 | session.Disconnected -= SessionOnDisconnected; 110 | UnregisterSession(session.Id); 111 | 112 | Logger.Information("{id} Session closed.", session.Id); 113 | OnSessionClosed(session); 114 | } 115 | } 116 | 117 | protected virtual void OnInitialize() 118 | { 119 | } 120 | 121 | protected virtual void OnListen() 122 | { 123 | } 124 | 125 | protected virtual void OnShutdown() 126 | { 127 | } 128 | 129 | protected virtual void OnSessionOpened(TSession session) 130 | { 131 | } 132 | 133 | protected virtual void OnSessionClosed(TSession session) 134 | { 135 | } 136 | 137 | protected virtual TSession CreateSession() 138 | { 139 | return Activator.CreateInstance(); 140 | } 141 | 142 | private void RegisterSession(TSession session) 143 | { 144 | _sessions.TryAdd(session.Id, session); 145 | } 146 | 147 | private void UnregisterSession(Guid sessionId) 148 | { 149 | if (_sessions.TryRemove(sessionId, out var session)) 150 | { 151 | session.Dispose(); 152 | } 153 | } 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /MiniMe.Core/Net/TcpSession.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net.Sockets; 4 | using MiniMe.Core.IO; 5 | using MiniMe.Core.Net.Transform; 6 | 7 | namespace MiniMe.Core.Net 8 | { 9 | public class TcpSession : IDisposable 10 | { 11 | protected const int bufferSize = 8192; 12 | 13 | public event EventHandler Disconnected; 14 | 15 | public Guid Id { get; } 16 | 17 | private Socket _socket; 18 | 19 | // receive 20 | private bool _receiving; 21 | private SocketAsyncEventArgs _receiveEventArg; 22 | private ByteBuffer _receiveBuffer; 23 | 24 | // packet 25 | private readonly List _recvTransforms; 26 | private readonly List _sendTransforms; 27 | 28 | public TcpSession() 29 | { 30 | Id = Guid.NewGuid(); 31 | _recvTransforms = new List(); 32 | _sendTransforms = new List(); 33 | } 34 | 35 | protected virtual void OnConnected() 36 | { 37 | } 38 | 39 | protected virtual void OnPacketReceived(ReadOnlySpan packet, DateTime reciveTime) 40 | { 41 | } 42 | 43 | protected virtual void OnBadPacketReceived(ReadOnlySpan packet, DateTime reciveTime, Exception exception) 44 | { 45 | } 46 | 47 | protected void AddReceiveTransform(IPacketTransform transform) 48 | { 49 | _recvTransforms.Add(transform); 50 | } 51 | 52 | protected void AddSendTransform(IPacketTransform transform) 53 | { 54 | _sendTransforms.Add(transform); 55 | } 56 | 57 | protected int Send(ReadOnlySpan packet) 58 | { 59 | foreach (var transform in _sendTransforms) 60 | { 61 | packet = transform.Transform(ref packet); 62 | } 63 | 64 | int sent = _socket.Send(packet, SocketFlags.None, out var error); 65 | 66 | if (error != SocketError.Success) 67 | { 68 | Disconnect(); 69 | } 70 | 71 | return sent; 72 | } 73 | 74 | protected int Send(byte[] packet) 75 | { 76 | return Send(packet.AsSpan()); 77 | } 78 | 79 | protected int Send(byte[] packet, int offset, int length) 80 | { 81 | return Send(packet.AsSpan(offset, length)); 82 | } 83 | 84 | internal void Connect(Socket socket) 85 | { 86 | _socket = socket; 87 | _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); 88 | _socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); 89 | 90 | _receiveEventArg = new SocketAsyncEventArgs(); 91 | _receiveEventArg.Completed += OnAsyncCompleted; 92 | _receiveBuffer = new ByteBuffer(bufferSize); 93 | 94 | OnConnected(); 95 | } 96 | 97 | internal void StartReceive() 98 | { 99 | NextReceive(); 100 | } 101 | 102 | private void OnAsyncCompleted(object sender, SocketAsyncEventArgs e) 103 | { 104 | switch (e.LastOperation) 105 | { 106 | case SocketAsyncOperation.Receive: 107 | if (ProcessReceive(e)) 108 | NextReceive(); 109 | 110 | break; 111 | 112 | case SocketAsyncOperation.Send: 113 | break; 114 | 115 | default: 116 | throw new InvalidOperationException(); 117 | } 118 | } 119 | 120 | private void NextReceive() 121 | { 122 | if (_receiving) 123 | return; 124 | 125 | bool process = true; 126 | 127 | while (process) 128 | { 129 | process = false; 130 | 131 | try 132 | { 133 | _receiving = true; 134 | _receiveEventArg.SetBuffer(_receiveBuffer.Data); 135 | 136 | if (!_socket.ReceiveAsync(_receiveEventArg)) 137 | { 138 | process = ProcessReceive(_receiveEventArg); 139 | } 140 | } 141 | catch (ObjectDisposedException) 142 | { 143 | } 144 | } 145 | } 146 | 147 | private bool ProcessReceive(SocketAsyncEventArgs e) 148 | { 149 | int size = e.BytesTransferred; 150 | 151 | if (size > 0) 152 | { 153 | ProcessPacket(_receiveBuffer.Data, 0, size); 154 | 155 | if (_receiveBuffer.Length == size) 156 | { 157 | _receiveBuffer.Resize(size * 2); 158 | } 159 | } 160 | 161 | _receiving = false; 162 | 163 | if (e.SocketError == SocketError.Success) 164 | { 165 | if (size > 0) 166 | { 167 | return true; 168 | } 169 | } 170 | 171 | Disconnect(); 172 | 173 | return false; 174 | } 175 | 176 | private void ProcessPacket(byte[] packet, int offset, int size) 177 | { 178 | var reciveTime = DateTime.Now; 179 | ReadOnlySpan buffer = packet.AsSpan(offset, size); 180 | 181 | try 182 | { 183 | foreach (var transform in _recvTransforms) 184 | { 185 | buffer = transform.Transform(ref buffer); 186 | } 187 | } 188 | catch (Exception e) 189 | { 190 | OnBadPacketReceived(packet.AsSpan(offset, size), reciveTime, e); 191 | return; 192 | } 193 | 194 | OnPacketReceived(buffer, reciveTime); 195 | } 196 | 197 | private void Disconnect() 198 | { 199 | if (_socket == null) 200 | return; 201 | 202 | try 203 | { 204 | _socket.Shutdown(SocketShutdown.Both); 205 | } 206 | catch (Exception e) when (e is SocketException || e is ObjectDisposedException) 207 | { 208 | } 209 | 210 | _socket.Close(); 211 | _socket.Dispose(); 212 | 213 | Disconnected?.Invoke(this, EventArgs.Empty); 214 | } 215 | 216 | public void Dispose() 217 | { 218 | if (_socket != null) 219 | { 220 | Disconnect(); 221 | } 222 | 223 | _socket = null; 224 | } 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /MiniMe.Core/Net/Transform/CryptoPacketTransform.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Cryptography; 3 | using MiniMe.Core.IO; 4 | 5 | namespace MiniMe.Core.Net.Transform 6 | { 7 | public class CryptoPacketTransform : IPacketTransform 8 | { 9 | private readonly ICryptoTransform _cryptoTransform; 10 | private ByteBuffer _incompleteBlock; 11 | private readonly bool _useBuffering; 12 | 13 | public CryptoPacketTransform(ICryptoTransform cryptoTransform, bool useBuffering = false) 14 | { 15 | _cryptoTransform = cryptoTransform; 16 | _useBuffering = useBuffering; 17 | } 18 | 19 | public ReadOnlySpan Transform(ref ReadOnlySpan packet) 20 | { 21 | byte[] packetBin; 22 | 23 | if (_useBuffering) 24 | { 25 | if (_incompleteBlock != null) 26 | { 27 | int incompleteLength = _incompleteBlock.Length; 28 | 29 | _incompleteBlock.Resize(incompleteLength + packet.Length); 30 | packet.CopyTo(_incompleteBlock.Data.AsSpan(incompleteLength)); 31 | 32 | packet = _incompleteBlock.Data; 33 | _incompleteBlock = null; 34 | } 35 | 36 | int remain = packet.Length % _cryptoTransform.InputBlockSize; 37 | 38 | if (remain > 0) 39 | { 40 | _incompleteBlock = new ByteBuffer(packet.Slice(packet.Length - remain).ToArray()); 41 | } 42 | 43 | packetBin = packet.Slice(0, packet.Length - remain).ToArray(); 44 | } 45 | else 46 | { 47 | packetBin = packet.ToArray(); 48 | } 49 | 50 | return _cryptoTransform.TransformFinalBlock(packetBin, 0, packetBin.Length); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /MiniMe.Core/Net/Transform/IPacketTransform.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MiniMe.Core.Net.Transform 4 | { 5 | public interface IPacketTransform 6 | { 7 | ReadOnlySpan Transform(ref ReadOnlySpan packet); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Core/ServerBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Reflection; 4 | using Serilog; 5 | using Serilog.Events; 6 | using Serilog.Sinks.SystemConsole.Themes; 7 | 8 | namespace MiniMe.Core 9 | { 10 | public abstract class ServerBase 11 | { 12 | public IPEndPoint EndPoint { get; } 13 | 14 | public ILogger Logger { get; } 15 | 16 | protected ServerBase(IPEndPoint endPoint) 17 | { 18 | EndPoint = endPoint ?? throw new ArgumentNullException(nameof(endPoint)); 19 | 20 | var name = GetLoggerName(); 21 | 22 | Logger = new LoggerConfiguration() 23 | .MinimumLevel.Verbose() 24 | .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) 25 | .MinimumLevel.Override("Microsoft.AspNetCore.Hosting", LogEventLevel.Information) 26 | .MinimumLevel.Override("Microsoft.EntityFrameworkCore.Database.Command", LogEventLevel.Warning) 27 | .Enrich.FromLogContext() 28 | .WriteTo.Console( 29 | theme: AnsiConsoleTheme.Code, 30 | outputTemplate: $"[{name} {{Timestamp:HH:mm:ss}} {{Level:u3}}] {{Message:lj}}{{NewLine}}{{Exception}}") 31 | .CreateLogger(); 32 | } 33 | 34 | private string GetLoggerName() 35 | { 36 | var nameAttribute = GetType().GetCustomAttribute(); 37 | return nameAttribute?.Name ?? GetType().Name; 38 | } 39 | 40 | public abstract void Start(); 41 | 42 | public abstract void Stop(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /MiniMe.Core/Services/IAimeService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MiniMe.Core.Repositories 4 | { 5 | public interface IAimeService 6 | { 7 | Guid? FindIdByCardId(int cardId); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MiniMe.Core/Services/ISwitchBoardService.cs: -------------------------------------------------------------------------------- 1 | using MiniMe.Core.Models; 2 | 3 | namespace MiniMe.Core.Repositories 4 | { 5 | public interface ISwitchBoardService 6 | { 7 | string Host { get; } 8 | 9 | MiniMePorts Ports { get; } 10 | 11 | string GetStartupHost(string gameId); 12 | 13 | string GetStartupUri(string gameId); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MiniMe.Core/SwitchBoard.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using MiniMe.Core.Models; 3 | using MiniMe.Core.Repositories; 4 | 5 | namespace MiniMe.Core 6 | { 7 | public class SwitchBoard : ISwitchBoardService 8 | { 9 | public string Host { get; } 10 | 11 | public MiniMePorts Ports { get; } 12 | 13 | private readonly Dictionary _startupHosts; 14 | private readonly Dictionary _startupUris; 15 | 16 | public SwitchBoard(string host, MiniMePorts ports) 17 | { 18 | Host = host; 19 | Ports = ports; 20 | 21 | _startupHosts = new Dictionary 22 | { 23 | ["SDDF"] = $"{host}:{ports.Idz.UserDb.Tcp}" 24 | }; 25 | 26 | _startupUris = new Dictionary 27 | { 28 | ["SDBT"] = $"http://{host}:{ports.Chunithm}/", 29 | ["SBZV"] = $"http://{host}:{ports.Diva}/" 30 | }; 31 | } 32 | 33 | public string GetStartupHost(string gameId) 34 | { 35 | if (_startupHosts.TryGetValue(gameId, out var result)) 36 | return result; 37 | 38 | return null; 39 | } 40 | 41 | public string GetStartupUri(string gameId) 42 | { 43 | if (_startupUris.TryGetValue(gameId, out var result)) 44 | return result; 45 | 46 | return null; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /MiniMe.Core/Utilities/ConsoleUtility.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace MiniMe.Core.Utilities 5 | { 6 | public static class ConsoleUtility 7 | { 8 | private static Action _callbacks; 9 | 10 | static ConsoleUtility() 11 | { 12 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 13 | { 14 | SetConsoleCtrlHandler(WindowCtrlHandler, true); 15 | } 16 | 17 | AppDomain.CurrentDomain.ProcessExit += (s, e) => OnExit(); 18 | } 19 | 20 | public static void HookExit(Action callback) 21 | { 22 | _callbacks += callback ?? throw new ArgumentNullException(nameof(callback)); 23 | } 24 | 25 | private static void OnExit() 26 | { 27 | _callbacks?.Invoke(); 28 | _callbacks = null; 29 | } 30 | 31 | private static bool WindowCtrlHandler(CtrlType signal) 32 | { 33 | OnExit(); 34 | return true; 35 | } 36 | 37 | #region Windows 38 | [DllImport("Kernel32")] 39 | private static extern bool SetConsoleCtrlHandler(SetConsoleCtrlEventHandler handler, bool add); 40 | 41 | private delegate bool SetConsoleCtrlEventHandler(CtrlType signal); 42 | 43 | private enum CtrlType 44 | { 45 | CEvent = 0, 46 | BreakEvent = 1, 47 | CloseEvent = 2, 48 | LogoffEvent = 5, 49 | ShutdownEvent = 6 50 | } 51 | #endregion 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /MiniMe.Core/Utilities/HexUtility.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Numerics; 3 | 4 | namespace MiniMe.Core.Utilities 5 | { 6 | public static class HexUtility 7 | { 8 | public static byte[] HexToBytes(ReadOnlySpan hex) 9 | { 10 | var result = new byte[hex.Length / 2]; 11 | 12 | for (int i = 0; i < result.Length; i++) 13 | { 14 | int high = hex[i * 2]; 15 | int low = hex[i * 2 + 1]; 16 | 17 | high = (high & 0xf) + ((high & 0x40) >> 6) * 9; 18 | low = (low & 0xf) + ((low & 0x40) >> 6) * 9; 19 | 20 | result[i] = (byte)((high << 4) | low); 21 | } 22 | 23 | return result; 24 | } 25 | 26 | public static string HexToDecimalString(ReadOnlySpan hex) 27 | { 28 | return new BigInteger(HexToBytes(hex), true, true).ToString(); 29 | } 30 | 31 | public static string BytesToHex(ReadOnlySpan bytes) 32 | { 33 | Span buffer = stackalloc char[bytes.Length * 2]; 34 | 35 | for (int i = 0; i < bytes.Length; i++) 36 | { 37 | var b = bytes[i] >> 4; 38 | buffer[i * 2] = (char)(55 + b + (((b - 10) >> 31) & -7)); 39 | b = bytes[i] & 0xF; 40 | buffer[i * 2 + 1] = (char)(55 + b + (((b - 10) >> 31) & -7)); 41 | } 42 | 43 | return buffer.ToString(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MiniMe.Core/Utilities/ProcessEnvironment.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MiniMe.Core.Utilities 4 | { 5 | public static class ProcessEnvironment 6 | { 7 | public static string GetEnvironmentVariable(string variable) 8 | { 9 | return Environment.GetEnvironmentVariable(variable, EnvironmentVariableTarget.Process); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /MiniMe.Core/Utilities/ResourceManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.IO; 4 | using System.Reflection; 5 | 6 | namespace MiniMe.Core.Utilities 7 | { 8 | public static class ResourceManager 9 | { 10 | private static string GetFullResourceName(Assembly assembly, string resourceName) 11 | { 12 | return $"{assembly.GetName().Name}.Resources.{resourceName}"; 13 | } 14 | 15 | public static Stream GetResourceStream([NotNull] string resourceName) 16 | { 17 | var assembly = Assembly.GetCallingAssembly(); 18 | resourceName = GetFullResourceName(assembly, resourceName); 19 | 20 | return assembly.GetManifestResourceStream(resourceName); 21 | } 22 | 23 | public static byte[] GetResourceBytes([NotNull] string resourceName) 24 | { 25 | var assembly = Assembly.GetCallingAssembly(); 26 | resourceName = GetFullResourceName(assembly, resourceName); 27 | 28 | var stream = assembly.GetManifestResourceStream(resourceName) ?? throw new KeyNotFoundException(resourceName); 29 | using var ms = new MemoryStream(); 30 | stream.CopyTo(ms); 31 | 32 | return ms.ToArray(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /MiniMe.Core/Utilities/Validation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MiniMe.Core.Utilities 4 | { 5 | internal static class Validation 6 | { 7 | public static void ArgumentNotNull(object value, string parameterName) 8 | { 9 | if (value == null) 10 | throw new ArgumentNullException(parameterName); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /MiniMe.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniMe", "MiniMe\MiniMe.csproj", "{34995AEF-B6C8-41EC-8967-83ACC9363BA2}" 4 | EndProject 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniMe.AllNet", "MiniMe.AllNet\MiniMe.AllNet.csproj", "{E958C67F-56CE-413C-9887-0F7FA12EB3A4}" 6 | EndProject 7 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Servers", "Servers", "{B0D6E222-7C24-412F-BB20-3B328AB1E202}" 8 | EndProject 9 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniMe.Core", "MiniMe.Core\MiniMe.Core.csproj", "{8D8D4836-8652-49C8-AD53-AA6BF86FEE3B}" 10 | EndProject 11 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniMe.Billing", "MiniMe.Billing\MiniMe.Billing.csproj", "{9633116B-013F-4113-995F-D4CC5821A852}" 12 | EndProject 13 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniMe.Aime", "MiniMe.Aime\MiniMe.Aime.csproj", "{282939B1-5020-4432-9543-385C9090EA46}" 14 | EndProject 15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniMe.Chunithm", "MiniMe.Chunithm\MiniMe.Chunithm.csproj", "{DB64EDA2-D781-4B45-9BFE-37B8813F5B06}" 16 | EndProject 17 | Global 18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 19 | Debug|Any CPU = Debug|Any CPU 20 | Release|Any CPU = Release|Any CPU 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {34995AEF-B6C8-41EC-8967-83ACC9363BA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {34995AEF-B6C8-41EC-8967-83ACC9363BA2}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {34995AEF-B6C8-41EC-8967-83ACC9363BA2}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {34995AEF-B6C8-41EC-8967-83ACC9363BA2}.Release|Any CPU.Build.0 = Release|Any CPU 27 | {E958C67F-56CE-413C-9887-0F7FA12EB3A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 28 | {E958C67F-56CE-413C-9887-0F7FA12EB3A4}.Debug|Any CPU.Build.0 = Debug|Any CPU 29 | {E958C67F-56CE-413C-9887-0F7FA12EB3A4}.Release|Any CPU.ActiveCfg = Release|Any CPU 30 | {E958C67F-56CE-413C-9887-0F7FA12EB3A4}.Release|Any CPU.Build.0 = Release|Any CPU 31 | {8D8D4836-8652-49C8-AD53-AA6BF86FEE3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 32 | {8D8D4836-8652-49C8-AD53-AA6BF86FEE3B}.Debug|Any CPU.Build.0 = Debug|Any CPU 33 | {8D8D4836-8652-49C8-AD53-AA6BF86FEE3B}.Release|Any CPU.ActiveCfg = Release|Any CPU 34 | {8D8D4836-8652-49C8-AD53-AA6BF86FEE3B}.Release|Any CPU.Build.0 = Release|Any CPU 35 | {9633116B-013F-4113-995F-D4CC5821A852}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 36 | {9633116B-013F-4113-995F-D4CC5821A852}.Debug|Any CPU.Build.0 = Debug|Any CPU 37 | {9633116B-013F-4113-995F-D4CC5821A852}.Release|Any CPU.ActiveCfg = Release|Any CPU 38 | {9633116B-013F-4113-995F-D4CC5821A852}.Release|Any CPU.Build.0 = Release|Any CPU 39 | {282939B1-5020-4432-9543-385C9090EA46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 40 | {282939B1-5020-4432-9543-385C9090EA46}.Debug|Any CPU.Build.0 = Debug|Any CPU 41 | {282939B1-5020-4432-9543-385C9090EA46}.Release|Any CPU.ActiveCfg = Release|Any CPU 42 | {282939B1-5020-4432-9543-385C9090EA46}.Release|Any CPU.Build.0 = Release|Any CPU 43 | {DB64EDA2-D781-4B45-9BFE-37B8813F5B06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 44 | {DB64EDA2-D781-4B45-9BFE-37B8813F5B06}.Debug|Any CPU.Build.0 = Debug|Any CPU 45 | {DB64EDA2-D781-4B45-9BFE-37B8813F5B06}.Release|Any CPU.ActiveCfg = Release|Any CPU 46 | {DB64EDA2-D781-4B45-9BFE-37B8813F5B06}.Release|Any CPU.Build.0 = Release|Any CPU 47 | EndGlobalSection 48 | GlobalSection(NestedProjects) = preSolution 49 | {E958C67F-56CE-413C-9887-0F7FA12EB3A4} = {B0D6E222-7C24-412F-BB20-3B328AB1E202} 50 | {9633116B-013F-4113-995F-D4CC5821A852} = {B0D6E222-7C24-412F-BB20-3B328AB1E202} 51 | {282939B1-5020-4432-9543-385C9090EA46} = {B0D6E222-7C24-412F-BB20-3B328AB1E202} 52 | {DB64EDA2-D781-4B45-9BFE-37B8813F5B06} = {B0D6E222-7C24-412F-BB20-3B328AB1E202} 53 | EndGlobalSection 54 | EndGlobal 55 | -------------------------------------------------------------------------------- /MiniMe/MiniMe.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /MiniMe/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Text; 8 | using System.Threading; 9 | using Microsoft.Extensions.Configuration; 10 | using MiniMe.Aime; 11 | using MiniMe.AllNet; 12 | using MiniMe.Billing; 13 | using MiniMe.Chunithm; 14 | using MiniMe.Core; 15 | using MiniMe.Core.AspNetCore.Extensions; 16 | using MiniMe.Core.Models; 17 | using MiniMe.Core.Repositories; 18 | using MiniMe.Core.Utilities; 19 | using Serilog; 20 | using Serilog.Sinks.SystemConsole.Themes; 21 | 22 | namespace MiniMe 23 | { 24 | public static class Program 25 | { 26 | private static ServerBase[] _servers; 27 | private static bool _terminating; 28 | 29 | private static void Initialize() 30 | { 31 | // Encodings 32 | 33 | Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); 34 | 35 | // Logger 36 | 37 | Log.Logger = new LoggerConfiguration() 38 | .WriteTo.Console( 39 | theme: AnsiConsoleTheme.Code, 40 | outputTemplate: "[MiniMe {Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}") 41 | .CreateLogger(); 42 | 43 | // SwitchBoard 44 | 45 | var config = new ConfigurationBuilder() 46 | .SetBasePath(Directory.GetCurrentDirectory()) 47 | .AddJsonFile("appsettings.json", false) 48 | .Build(); 49 | 50 | MiniMeService.Add( 51 | new SwitchBoard( 52 | config.GetValue("Host"), 53 | config.GetOptions("Port"))); 54 | 55 | // Hook console terminate request for windows 56 | ConsoleUtility.HookExit(Terminate); 57 | } 58 | 59 | public static int Main() 60 | { 61 | Initialize(); 62 | 63 | _servers = CreateServers().ToArray(); 64 | 65 | Log.Information("Starting"); 66 | 67 | var exceptinoBag = new ConcurrentBag(); 68 | var serverEvent = new CountdownEvent(_servers.Length); 69 | 70 | foreach (var server in _servers) 71 | { 72 | var thr = new Thread(() => 73 | { 74 | try 75 | { 76 | server.Start(); 77 | } 78 | catch (Exception e) 79 | { 80 | exceptinoBag.Add(e); 81 | Terminate(); 82 | } 83 | finally 84 | { 85 | if (server is IDisposable disposable) 86 | { 87 | disposable.Dispose(); 88 | } 89 | 90 | serverEvent.Signal(); 91 | } 92 | }) 93 | { 94 | IsBackground = true 95 | }; 96 | 97 | thr.Start(); 98 | } 99 | 100 | serverEvent.Wait(); 101 | 102 | try 103 | { 104 | if (exceptinoBag.Count > 0) 105 | { 106 | Log.Fatal(new AggregateException(exceptinoBag), "Terminated unexpectedly"); 107 | return 1; 108 | } 109 | 110 | Log.Information("Terminated successfully"); 111 | return 0; 112 | } 113 | finally 114 | { 115 | Log.CloseAndFlush(); 116 | } 117 | } 118 | 119 | private static void Terminate() 120 | { 121 | if (_terminating) 122 | { 123 | return; 124 | } 125 | 126 | _terminating = true; 127 | Log.Information("Terminating.."); 128 | 129 | foreach (var server in _servers) 130 | { 131 | server.Stop(); 132 | } 133 | } 134 | 135 | private static IEnumerable CreateServers() 136 | { 137 | var switchBoard = MiniMeService.Get(); 138 | var dnsEntry = Dns.GetHostEntry(switchBoard.Host); 139 | 140 | if (dnsEntry.AddressList.Length == 0) 141 | throw new Exception("Dns address not found."); 142 | 143 | var address = dnsEntry.AddressList[0]; 144 | 145 | yield return new AimeServer(new IPEndPoint(address, switchBoard.Ports.Aime)); 146 | yield return new AllNetServer(new IPEndPoint(address, switchBoard.Ports.AllNet)); 147 | yield return new ChunithmServer(new IPEndPoint(address, switchBoard.Ports.Chunithm)); 148 | yield return new BillingServer(new IPEndPoint(address, switchBoard.Ports.Billing)); 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /MiniMe/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:57038", 8 | "sslPort": 44385 9 | } 10 | }, 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "MiniMe": { 19 | "commandName": "Project", 20 | "environmentVariables": { 21 | "ASPNETCORE_ENVIRONMENT": "Development" 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /MiniMe/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "Host": "127.0.0.1", 10 | "Port": { 11 | "Aime": 22345, 12 | "AllNet": 80, 13 | "Billing": 8443, 14 | "Chunithm": 9001, 15 | "Diva": 9000, 16 | "Idz": { 17 | "UserDb": { 18 | "Tcp": 10000, 19 | "Http": 10001 20 | }, 21 | "Match": { 22 | "Tcp": 10002, 23 | "UdpSend": 10003, 24 | "UdpRecv": 10004 25 | }, 26 | "TagMatch": { 27 | "Tcp": 10005, 28 | "UdpSend": 10006, 29 | "UdpRecv": 10007 30 | }, 31 | "Event": 10008, 32 | "ScreenShot": 10009, 33 | "Echo1": 10010, 34 | "Echo2": 10011 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /PubKeyInfra/billing.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAML2GPUuzv2N4bYC 3 | xtc5bZSzolHFWdCUbP+whjr3K98FOLnYeoi7mtUSUUYOW8wIqy6WM3c4c0Bp7FcQ 4 | LnZ0zWMm1TfLGHZzZmk5n7Iv6HDPr3ehDgbWLnOpRrVqZDxpAGD2vQb4p2DW4I2x 5 | GUqnqDa++C8dH/0lXqE6cqwGXNGtAgMBAAECgYEAizgPhG4Dk55QkpeTBDfXH3vT 6 | Ko9B3qdO2ptkjxDX/C8PXe7POXq2SvcEoIE6Xg3Gp8LMR5NBAbth8J32f9JSov3P 7 | SiGCGno4k2i2s3jRuVg76FGLDsZH/N1dt4h78VnW0VlInwaM6bQv3zp0u8rXVk/P 8 | wpYh9AGmquBJS3VYUcECQQD0PDRe28SrhollygGZSO321rYbYhoTIstDXZWyQ/y/ 9 | PWKNwNHcYTHIVGmTrJx2AJUyr1tJhwjiOwlsI5Y1Q4/9AkEAzFpFPcs1r/xgSFxB 10 | eYrcNseWYbVajtVxG9t57sayaEQbH2UMNA2vqSYK/nU6oJhj5eLRIsPHlA5ZbIiZ 11 | rvc/cQJAKS0RQ0DX+ncXKQMSm+4wuGHgl+NFNB60mCnp+AEAVpmZyP5OI1J7myOo 12 | HQ6H3lkgzkfEIzRR6ho773BcfaRjXQJAfS4nEE11G9ML4AezjBLGB0CIHF6NlMWn 13 | PhtaPCy3iSt/OeIacaCYpJNLVMjXGx1+xIoG9rbbgRSxLs0W55lJ4QJBALOUVcNw 14 | GKEJdxhIkA8iuUlEyGpKluAgHUNOOKvC3ogRoB0OyH+If/9o8wWDfxgexgM0zGBc 15 | u178W9XDW+IijDA= 16 | -----END PRIVATE KEY----- 17 | -------------------------------------------------------------------------------- /PubKeyInfra/billing.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/evan-choi/MiniMe/f64d8eabffa14f73f91bc822b4470273864e13cb/PubKeyInfra/billing.pub -------------------------------------------------------------------------------- /PubKeyInfra/ca.crt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/evan-choi/MiniMe/f64d8eabffa14f73f91bc822b4470273864e13cb/PubKeyInfra/ca.crt -------------------------------------------------------------------------------- /PubKeyInfra/ca.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDeHEJ2L+FXrcdW 3 | G8LNZ/WknTzE9lsB4I1Gb7LcrXi/Yq+rEnF8iru2h4j1icmDSuwLBS//qENO2LfE 4 | +iU1zmtlhjAfGv8SYSXg1ssAbB6Sv4vvz0U0pNCAvnJ/K8UN7kAXHB1rw5dRvO47 5 | A+M1NO8S6pYTL5jJhK+BaNVmP6w9eOQ4c+0ZvKFOEX0E/uy1qcUuS386ZcPFRxRF 6 | vErUo8WjyMAwV9HZoVa3h3tAywKfDrYjF8DtdNG93G3igzpv4Iro4AuESrPE3t4x 7 | 5uiO4UxwUObolkVsmOAzo7g1QiEi0wlHTQX1ZH3dXgaRAF5vv/V02ZAnmI5keXfP 8 | DDIqURf3AgMBAAECggEAHQD3tNM/y+FHfHkXkRcYPqzBuL6q163pBN+lLagBcoyC 9 | gAZih27eYFGGkvmxNNHdzPqab/oa//rQ1IoNvd78qz9AnW87C71f4uJpk96Kh4M3 10 | 1NLuKJe1GnrEHNMsYktQVzQ2q1HZOrU/LrmtO89zwLadblfyza3j9TQpWbbK2SPn 11 | zVFlBZazX5s5APHgI9PymjPkwC9jsUbSrpe816W9KT8n8cG/CdS7relOXic5PWVL 12 | zgWQdCFMhY/aHFbLWM7RIkQTdX0GopJWgleLQqryKHIVu6Vekyrp/eOpl22wzjku 13 | DMWEK9ZWLHYejbCZJJIRKxSsxRlwAX2D/9kQ9vs2YQKBgQD/UYGD7ovAjTclJzyx 14 | d6dj/C0fHwyFnF+Lknll7AhA1hBYzQ2uaqBSUc2oV19dsxfZfy/tD0gP2ZVSFl1f 15 | iF3ON0xVbbb4r3Drck17c5iQ2+z5PHfOHSD3+AwF+stkKwLiJxIudJJppm1Cn6wc 16 | WiysnqeEhsaklOe0PvdA8BIkDwKBgQDetA7g2m7FKfODHb9Tx7qDtiRjsbCYD1fF 17 | UpF2yQ+twXJAO9AgkxYmmWMQ9/h+yxpsTjE4oDOO5K907x6gGzJFfFrDn0R0zIfw 18 | 0EobfwJ4l28rqUYvQzgYyc/UW2PiuLIr2otXQNmtOnYmPogLIMlgQSvEnseXCs// 19 | 0+TRKKbFmQKBgGVJYVcEeF6P5xOPKE3DCR3qOcBB4gbTTTgiiJR9eZy3D08bMdVC 20 | qY1etHaXCtcyKED5avrheBYJnGovQyWWBJi9aUPuvYqUlvhgpQpXhmvZQ35wlZqo 21 | BZ85wRNSNgPr6D3tgBH73uWYx3mJvI6W22gznIM/sGg0RmNEI3SYiKnTAoGAJ1mx 22 | d1GhWP08peJPuEIGVteMPoFbLsMnQxp/0XldZ9pSkb7/24Gh3FgmBQ2LvvusQ47d 23 | a6AC/DC0P/kwdCHaFCUQ9JfjxK+PJaHoNkuO6Df50MEsQZWjB95A9sjfMWRpNw56 24 | qIQw8kbuMXvDFhRJANUDIs7bfXjPn+iU+dAxB6ECgYEAusdd0y30VXE9Mj6zJ2Ee 25 | Cm1L9THijgcPH/Q7rD9Vk5yPSXuKO9Q2atgY0COOeQxwmwjf8UHYldDxLjor1nz0 26 | CdwQihCexJSXuoQ9LA/XeTLDm/F/M1Eze+MgOE23dT9qEUOwHrjDsyuYwfev7ir9 27 | a11MWJKcdkeKS/lGXeX3MbE= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /PubKeyInfra/ca.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDLTCCAhWgAwIBAgIUQ67cF8bq3m9pcWq6zJeZRc8N60EwDQYJKoZIhvcNAQEL 3 | BQAwJTEQMA4GA1UEAwwHRHVtbXlDQTERMA8GA1UECgwIRHVtbXlQS0kwIBcNMTgx 4 | MDE1MTkzMDUxWhgPMjExODEwMTUxOTMwNTFaMCUxEDAOBgNVBAMMB0R1bW15Q0Ex 5 | ETAPBgNVBAoMCER1bW15UEtJMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC 6 | AQEA3hxCdi/hV63HVhvCzWf1pJ08xPZbAeCNRm+y3K14v2KvqxJxfIq7toeI9YnJ 7 | g0rsCwUv/6hDTti3xPolNc5rZYYwHxr/EmEl4NbLAGwekr+L789FNKTQgL5yfyvF 8 | De5AFxwda8OXUbzuOwPjNTTvEuqWEy+YyYSvgWjVZj+sPXjkOHPtGbyhThF9BP7s 9 | tanFLkt/OmXDxUcURbxK1KPFo8jAMFfR2aFWt4d7QMsCnw62IxfA7XTRvdxt4oM6 10 | b+CK6OALhEqzxN7eMebojuFMcFDm6JZFbJjgM6O4NUIhItMJR00F9WR93V4GkQBe 11 | b7/1dNmQJ5iOZHl3zwwyKlEX9wIDAQABo1MwUTAdBgNVHQ4EFgQUxHdbXQ7dqFqw 12 | jzzl02L+UefEwNgwHwYDVR0jBBgwFoAUxHdbXQ7dqFqwjzzl02L+UefEwNgwDwYD 13 | VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEApcWGs+A06Aaqr9VAxhDp 14 | i4vSV0K++912IJWRv6rRRy7Hz4b7Ov5UOZ7AHshnQNWQvd9Qp+ehhNoLjL5joWk9 15 | BmwMPGAPhBAvidDh8QULUAIDJWDGF8CtDDaW8oHYjsBTBSVjKu1Ma/OVMc9vF0Ej 16 | MUb3LtlKZkNUqmUCjlE/V2bYYjqVLNTogrXO4KxXyqfBFdUzTCB/qX7V+HNnszDq 17 | IFHF+wyTklMSOwTUIrvW4R6zojXL0wjRdvtBqXSvPFq5HWJPdg0dfVyyVDZu7yPO 18 | 3gMJLqkDkHsaYLs2IKHUXqJCbHCJ/whpMWNYYozDFGrhetNSvo3sKht9wvQK08mc 19 | yg== 20 | -----END CERTIFICATE----- 21 | -------------------------------------------------------------------------------- /PubKeyInfra/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDg1xvj8JLt4nDq 3 | rRQOGzCys0bD2VdGRnQ/TYC3ezg0whYbQRD7bUdkNQm1KeNOlj8yr8kjz30swIY6 4 | 6Ufw82qGH0QjsmbSOTLr13B9K1ogd11aMxErvVnxtNBOkuwtzKL+Zb1D99jvxX0u 5 | e0dIsBcuojemyoz6iNbU7WSNtbIFeQFr+MlZujHIv0Hj76MYyZAqNq2F3Ou1SduV 6 | kw+Acol8KzTfiII38ibZcP+INgK6YvnrJrxbDZ+NXwsXOeg0y/vZ7hc2h1k5wT3E 7 | xWoyMD/bvnVrKTneQfwOI9s4s3pB6o1hGeUGRhPvpJ20+FGOE8LIRzBEixDKl82T 8 | G63DVoMJAgMBAAECggEBANKVBf0+BA8jZ4iUpFT16G1mdZ/W/uPF9viXGThAAwt+ 9 | wH+0ODiUSCo1dqsj2U5wcC6D74pHukBg7RdeCFBHW3zU6dfZLm40vlmfRS8mnFoO 10 | EfP6IlnqFcTJCdSdzPC0WfCUz2hKSPeA61bOhZwxuPSnYCIqUVIROczhrqz/AQYX 11 | ZuuY7ut0h6X11xoddeeTOdfd+rktxPVpHeJDcz9F6Gk/0pg1ezs66TZ5sWt0/ZhP 12 | ZWTB40KPec2lomRGwY36AMOT3uFucnbtJgxhTGdqsRv7Kl0xCTo7xW/85Za7rhXK 13 | +xRdHrYr9w6xYTKHi9Ap4HEmUcx/fGAtddxr0fzdpIECgYEA8nRyYYHMdSr4WI/E 14 | fD/cpIjKLxw9BCdoXhruVSKp1GmhyQTH7Y0zJQ0uvG7GlsEXJ2V9yqTofzWev8iQ 15 | vVzX+14yTKaNUAwc7HCEXMN+xqnq61Bjldx6U54CfdInOhTFuoq8CXu80cHobYMs 16 | 8SjnYuhp5NqABGR+9YTYaHzjBhkCgYEA7Wa9orxkWruXUdROUZrdhlU44ilxvA66 17 | r1vVVLQFNVle2hbie3b93ZQCZrZL8iFsGKOIhXSncQ6pl9GQqDLJvMUiffzUci6G 18 | A4GgGlzXpkj+RmAkIkGYafmQqTZhMHNws35LMYoIabn0l8cWwG0XL1pO2YSjaoYg 19 | 5Kj0TjoNonECgYAcAk3Qa+FFy+ACwyEMxYfkzhSlWprF5xOMg4ny9d0ut8FD6rR6 20 | Aezdo+c5R4bTlZzqJTRh+6kMQRKEz1PBPH+K/3fKGReMHsocmmcAHGmB49FKu++1 21 | OVI8ZK2fAW8cq5eoFCzi35ORm9gRBq1jcrlAWN8a3A8b8swj6uPhNkQ3yQKBgCH+ 22 | HBk5MIVtZvVomO5GZoHdog+AL7DlywVg+OLwA+7npRVFQZi8KQ2ZK97ZK3a4ImpE 23 | wD+bvH4Lw2zhrPzoiMpmz9GKakEPOFE4NlyP/rDossAQ9BuTmOdTvMr95lyxqumI 24 | o+usABhjcAprj25uMGuvWqr6uwt9uSgEqTaqSVmBAoGAMs6/59L8EABC/CkBLp0t 25 | y3sYzjyjZr6gnMCkIi95b2FWyIVjlK53dwjKYg67BUI8qLNbUW1NPhyotc/9GklP 26 | qiNTkUeKcHOlZqOzP0zPquFk2lSfJuuGrMgElZPcEFLsAWRqnjRGp5iP05nk5OQh 27 | foY7svzPedFk/t3eFcOyrPo= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /PubKeyInfra/server.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICtDCCAZwCAQAwDQYJKoZIhvcNAQELBQAwJTEQMA4GA1UEAwwHRHVtbXlDQTER 3 | MA8GA1UECgwIRHVtbXlQS0kwIBcNMTgxMDE1MTkzMDUxWhgPMjExODEwMTUxOTMw 4 | NTFaMBkxFzAVBgNVBAMMDmliLm5hb21pbmV0LmpwMIIBIjANBgkqhkiG9w0BAQEF 5 | AAOCAQ8AMIIBCgKCAQEA4Ncb4/CS7eJw6q0UDhswsrNGw9lXRkZ0P02At3s4NMIW 6 | G0EQ+21HZDUJtSnjTpY/Mq/JI899LMCGOulH8PNqhh9EI7Jm0jky69dwfStaIHdd 7 | WjMRK71Z8bTQTpLsLcyi/mW9Q/fY78V9LntHSLAXLqI3psqM+ojW1O1kjbWyBXkB 8 | a/jJWboxyL9B4++jGMmQKjathdzrtUnblZMPgHKJfCs034iCN/Im2XD/iDYCumL5 9 | 6ya8Ww2fjV8LFznoNMv72e4XNodZOcE9xMVqMjA/2751ayk53kH8DiPbOLN6QeqN 10 | YRnlBkYT76SdtPhRjhPCyEcwRIsQypfNkxutw1aDCQIDAQABMA0GCSqGSIb3DQEB 11 | CwUAA4IBAQANOqFqjnGf80vvwYEkUsfOWp8rNVat+8rdXl0BShGBXiDItzMOU79K 12 | YkPObniQ5RLBMhrvqlCsSk0Np+ZgvV12J4Wtmf/znLa5ZKyeI4N1FCefU9cl4xpB 13 | 08Fv8YWbYV7SMNr54ZkURdho4FVR1pAnpuittpAEjMT4R4ubbOH8UEbMTbVgxXdn 14 | 086IAlfsYn0gnOlf76RkJFLe4UlWaZB75SaaXnNavBPN9iFnqXLckg6tsFUJnNMC 15 | esq5aHQ9sXWs4oKpJi8SXxt/zNRmgTnQK2ONM38NeZpLmlWPkyNxzsRNlYWo+kWP 16 | C98jVFe1+3K88ISk0DSN4XOQQnrIvn68 17 | -----END CERTIFICATE----- 18 | -------------------------------------------------------------------------------- /PubKeyInfra/server.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/evan-choi/MiniMe/f64d8eabffa14f73f91bc822b4470273864e13cb/PubKeyInfra/server.pfx -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MiniMe 2 | A simple self-hosted AllNet/Aime server, written in .NET Core 3.1 3 | 4 | ## Features 5 | | Name | Server | Protocol | Database | 6 | | --- | --- | --- | -- | 7 | | ALLNet | ASP.NET Core, Kestrel | Http | | 8 | | Aime | System.Net.Socket | TCP | [EF Core](https://github.com/dotnet/efcore) (SQLite) | 9 | | Billing | ASP.NET Core, Kestrel | Https | | 10 | | Chunithm | ASP.NET Core, Kestrel | Http | [EF Core](https://github.com/dotnet/efcore) (SQLite) | 11 | 12 | ## How to run 13 | 14 | ### Requirements 15 | - [.NET Core SDK](https://dotnet.microsoft.com/download) 16 | 17 | ### Setup repository 18 | ```sh 19 | git clone https://github.com/evan-choi/MiniMe.git 20 | cd MiniMe 21 | ``` 22 | 23 | ### Run 24 | ```sh 25 | dotnet run 26 | ``` 27 | 28 | ## How to change DB provider 29 | 1. Setup [AimeContext](https://github.com/evan-choi/MiniMe/blob/master/MiniMe.Aime/Data/AimeContext.cs#L18) Configuring 30 | 31 | 2. Setup [ChunithmContext](https://github.com/evan-choi/MiniMe/blob/master/MiniMe.Chunithm/Data/ChunithmContext.cs#L18) Configuring 32 | 33 | ```cs 34 | protected override void OnConfiguring(DbContextOptionsBuilder options) 35 | { 36 | // Setup to the db provider you want 37 | options.UseMySql(/* mysql connection string */); 38 | } 39 | ``` 40 | --------------------------------------------------------------------------------