🐛 Fixes of lotteries and enrich features
This commit is contained in:
		| @@ -44,6 +44,10 @@ public class LotteryController(AppDatabase db, LotteryService lotteryService) : | |||||||
|         { |         { | ||||||
|             return BadRequest(err.Message); |             return BadRequest(err.Message); | ||||||
|         } |         } | ||||||
|  |         catch (InvalidOperationException err) | ||||||
|  |         { | ||||||
|  |             return BadRequest(err.Message); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     [HttpGet] |     [HttpGet] | ||||||
| @@ -80,21 +84,20 @@ public class LotteryController(AppDatabase db, LotteryService lotteryService) : | |||||||
|     [RequiredPermission("maintenance", "lotteries.draw.perform")] |     [RequiredPermission("maintenance", "lotteries.draw.perform")] | ||||||
|     public async Task<IActionResult> PerformLotteryDraw() |     public async Task<IActionResult> PerformLotteryDraw() | ||||||
|     { |     { | ||||||
|         await lotteryService.PerformDailyDrawAsync(); |         await lotteryService.DrawLotteries(); | ||||||
|         return Ok("Lottery draw performed successfully."); |         return Ok(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     [HttpGet("records")] |     [HttpGet("records")] | ||||||
|     [Authorize] |  | ||||||
|     public async Task<ActionResult<List<SnLotteryRecord>>> GetLotteryRecords( |     public async Task<ActionResult<List<SnLotteryRecord>>> GetLotteryRecords( | ||||||
|         [FromQuery] Instant? startDate = null, |         [FromQuery] Instant? startDate = null, | ||||||
|         [FromQuery] Instant? endDate = null, |         [FromQuery] Instant? endDate = null, | ||||||
|         [FromQuery] int offset = 0, |         [FromQuery] int offset = 0, | ||||||
|         [FromQuery] int limit = 20) |         [FromQuery] int limit = 20) | ||||||
|     { |     { | ||||||
|         if (HttpContext.Items["CurrentUser"] is not SnAccount currentUser) return Unauthorized(); |         var query = db.LotteryRecords | ||||||
|  |             .OrderByDescending(r => r.CreatedAt) | ||||||
|         var query = db.LotteryRecords.AsQueryable(); |             .AsQueryable(); | ||||||
|  |  | ||||||
|         if (startDate.HasValue) |         if (startDate.HasValue) | ||||||
|             query = query.Where(r => r.DrawDate >= startDate.Value); |             query = query.Where(r => r.DrawDate >= startDate.Value); | ||||||
| @@ -105,7 +108,6 @@ public class LotteryController(AppDatabase db, LotteryService lotteryService) : | |||||||
|         Response.Headers["X-Total"] = total.ToString(); |         Response.Headers["X-Total"] = total.ToString(); | ||||||
|  |  | ||||||
|         var records = await query |         var records = await query | ||||||
|             .OrderByDescending(r => r.DrawDate) |  | ||||||
|             .Skip(offset) |             .Skip(offset) | ||||||
|             .Take(limit) |             .Take(limit) | ||||||
|             .ToListAsync(); |             .ToListAsync(); | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ public class LotteryDrawJob(LotteryService lotteryService, ILogger<LotteryDrawJo | |||||||
|  |  | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             await lotteryService.PerformDailyDrawAsync(); |             await lotteryService.DrawLotteries(); | ||||||
|             logger.LogInformation("Daily lottery draw completed successfully."); |             logger.LogInformation("Daily lottery draw completed successfully."); | ||||||
|         } |         } | ||||||
|         catch (Exception ex) |         catch (Exception ex) | ||||||
|   | |||||||
| @@ -1,12 +1,28 @@ | |||||||
| using DysonNetwork.Shared.Models; | using DysonNetwork.Shared.Models; | ||||||
| using DysonNetwork.Pass.Wallet; | using DysonNetwork.Pass.Wallet; | ||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
|  | using Microsoft.Extensions.Logging; | ||||||
| using NodaTime; | using NodaTime; | ||||||
|  | using System.Text.Json; | ||||||
|  |  | ||||||
| namespace DysonNetwork.Pass.Lotteries; | namespace DysonNetwork.Pass.Lotteries; | ||||||
|  |  | ||||||
| public class LotteryService(AppDatabase db, PaymentService paymentService, WalletService walletService) | public class LotteryOrderMetaData | ||||||
| { | { | ||||||
|  |     public Guid AccountId { get; set; } | ||||||
|  |     public List<int> RegionOneNumbers { get; set; } = new(); | ||||||
|  |     public int RegionTwoNumber { get; set; } | ||||||
|  |     public int Multiplier { get; set; } = 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | public class LotteryService( | ||||||
|  |     AppDatabase db, | ||||||
|  |     PaymentService paymentService, | ||||||
|  |     WalletService walletService, | ||||||
|  |     ILogger<LotteryService> logger) | ||||||
|  | { | ||||||
|  |     private readonly ILogger<LotteryService> _logger = logger; | ||||||
|  |  | ||||||
|     private static bool ValidateNumbers(List<int> region1, int region2) |     private static bool ValidateNumbers(List<int> region1, int region2) | ||||||
|     { |     { | ||||||
|         if (region1.Count != 5 || region1.Distinct().Count() != 5) |         if (region1.Count != 5 || region1.Distinct().Count() != 5) | ||||||
| @@ -62,19 +78,33 @@ public class LotteryService(AppDatabase db, PaymentService paymentService, Walle | |||||||
|         return 10 + (multiplier - 1) * 10; |         return 10 + (multiplier - 1) * 10; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task<SnWalletOrder> CreateLotteryOrderAsync(Guid accountId, List<int> region1, int region2, int multiplier = 1) |     public async Task<SnWalletOrder> CreateLotteryOrderAsync(Guid accountId, List<int> region1, int region2, | ||||||
|  |         int multiplier = 1) | ||||||
|     { |     { | ||||||
|         if (!ValidateNumbers(region1, region2)) |         if (!ValidateNumbers(region1, region2)) | ||||||
|             throw new ArgumentException("Invalid lottery numbers"); |             throw new ArgumentException("Invalid lottery numbers"); | ||||||
|  |  | ||||||
|         var now = SystemClock.Instance.GetCurrentInstant(); |         var now = SystemClock.Instance.GetCurrentInstant(); | ||||||
|         var todayStart = new LocalDateTime(now.InUtc().Year, now.InUtc().Month, now.InUtc().Day, 0, 0).InUtc().ToInstant(); |         var todayStart = new LocalDateTime(now.InUtc().Year, now.InUtc().Month, now.InUtc().Day, 0, 0).InUtc() | ||||||
|         var hasPurchasedToday = await db.Lotteries.AnyAsync(l => l.AccountId == accountId && l.CreatedAt >= todayStart); |             .ToInstant(); | ||||||
|  |         var hasPurchasedToday = await db.Lotteries.AnyAsync(l => | ||||||
|  |             l.AccountId == accountId && | ||||||
|  |             l.CreatedAt >= todayStart && | ||||||
|  |             l.DrawStatus == LotteryDrawStatus.Pending | ||||||
|  |         ); | ||||||
|         if (hasPurchasedToday) |         if (hasPurchasedToday) | ||||||
|             throw new InvalidOperationException("You can only purchase one lottery per day."); |             throw new InvalidOperationException("You can only purchase one lottery per day."); | ||||||
|  |  | ||||||
|         var price = CalculateLotteryPrice(multiplier); |         var price = CalculateLotteryPrice(multiplier); | ||||||
|  |  | ||||||
|  |         var lotteryData = new LotteryOrderMetaData | ||||||
|  |         { | ||||||
|  |             AccountId = accountId, | ||||||
|  |             RegionOneNumbers = region1, | ||||||
|  |             RegionTwoNumber = region2, | ||||||
|  |             Multiplier = multiplier | ||||||
|  |         }; | ||||||
|  |  | ||||||
|         return await paymentService.CreateOrderAsync( |         return await paymentService.CreateOrderAsync( | ||||||
|             null, |             null, | ||||||
|             WalletCurrency.SourcePoint, |             WalletCurrency.SourcePoint, | ||||||
| @@ -83,29 +113,33 @@ public class LotteryService(AppDatabase db, PaymentService paymentService, Walle | |||||||
|             productIdentifier: "lottery", |             productIdentifier: "lottery", | ||||||
|             meta: new Dictionary<string, object> |             meta: new Dictionary<string, object> | ||||||
|             { |             { | ||||||
|                 ["account_id"] = accountId.ToString(), |                 ["data"] = JsonSerializer.Serialize(lotteryData) | ||||||
|                 ["region_one_numbers"] = region1, |  | ||||||
|                 ["region_two_number"] = region2, |  | ||||||
|                 ["multiplier"] = multiplier |  | ||||||
|             }); |             }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task HandleLotteryOrder(SnWalletOrder order) |     public async Task HandleLotteryOrder(SnWalletOrder order) | ||||||
|     { |     { | ||||||
|  |         if (order.Status == OrderStatus.Finished) | ||||||
|  |             return; // Already processed | ||||||
|  |  | ||||||
|         if (order.Status != OrderStatus.Paid || |         if (order.Status != OrderStatus.Paid || | ||||||
|             !order.Meta.TryGetValue("account_id", out var accountIdValue) || |             !order.Meta.TryGetValue("data", out var dataValue) || | ||||||
|             !order.Meta.TryGetValue("region_one_numbers", out var region1Value) || |             dataValue is null || | ||||||
|             !order.Meta.TryGetValue("region_two_number", out var region2Value) || |             dataValue is not JsonElement { ValueKind: JsonValueKind.String } jsonElem) | ||||||
|             !order.Meta.TryGetValue("multiplier", out var multiplierValue)) |  | ||||||
|             throw new InvalidOperationException("Invalid order."); |             throw new InvalidOperationException("Invalid order."); | ||||||
|  |  | ||||||
|         var accountId = Guid.Parse((string)accountIdValue!); |         var jsonString = jsonElem.GetString(); | ||||||
|         var region1Json = (System.Text.Json.JsonElement)region1Value; |         if (jsonString is null) | ||||||
|         var region1 = region1Json.EnumerateArray().Select(e => e.GetInt32()).ToList(); |             throw new InvalidOperationException("Invalid order."); | ||||||
|         var region2 = Convert.ToInt32((string)region2Value!); |  | ||||||
|         var multiplier = Convert.ToInt32((string)multiplierValue!); |  | ||||||
|  |  | ||||||
|         await CreateTicketAsync(accountId, region1, region2, multiplier); |         var data = JsonSerializer.Deserialize<LotteryOrderMetaData>(jsonString); | ||||||
|  |         if (data is null) | ||||||
|  |             throw new InvalidOperationException("Invalid order data."); | ||||||
|  |  | ||||||
|  |         await CreateTicketAsync(data.AccountId, data.RegionOneNumbers, data.RegionTwoNumber, data.Multiplier); | ||||||
|  |  | ||||||
|  |         order.Status = OrderStatus.Finished; | ||||||
|  |         await db.SaveChangesAsync(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static int CalculateReward(int region1Matches, bool region2Match) |     private static int CalculateReward(int region1Matches, bool region2Match) | ||||||
| @@ -133,6 +167,7 @@ public class LotteryService(AppDatabase db, PaymentService paymentService, Walle | |||||||
|             var num = random.Next(min, max + 1); |             var num = random.Next(min, max + 1); | ||||||
|             if (!numbers.Contains(num)) numbers.Add(num); |             if (!numbers.Contains(num)) numbers.Add(num); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return numbers.OrderBy(n => n).ToList(); |         return numbers.OrderBy(n => n).ToList(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -141,24 +176,36 @@ public class LotteryService(AppDatabase db, PaymentService paymentService, Walle | |||||||
|         return playerNumbers.Intersect(winningNumbers).Count(); |         return playerNumbers.Intersect(winningNumbers).Count(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public async Task PerformDailyDrawAsync() |     public async Task DrawLotteries() | ||||||
|     { |     { | ||||||
|         var now = SystemClock.Instance.GetCurrentInstant(); |         try | ||||||
|         var yesterdayStart = new LocalDateTime(now.InUtc().Year, now.InUtc().Month, now.InUtc().Day, 0, 0).InUtc().ToInstant().Minus(Duration.FromDays(1)); |         { | ||||||
|         var todayStart = new LocalDateTime(now.InUtc().Year, now.InUtc().Month, now.InUtc().Day, 0, 0).InUtc().ToInstant(); |             _logger.LogInformation("Starting drawing lotteries..."); | ||||||
|  |  | ||||||
|         // Tickets purchased yesterday that are still pending draw |             var now = SystemClock.Instance.GetCurrentInstant(); | ||||||
|  |  | ||||||
|  |             // All pending lottery tickets | ||||||
|             var tickets = await db.Lotteries |             var tickets = await db.Lotteries | ||||||
|             .Where(l => l.CreatedAt >= yesterdayStart && l.CreatedAt < todayStart && l.DrawStatus == LotteryDrawStatus.Pending) |                 .Where(l => l.DrawStatus == LotteryDrawStatus.Pending) | ||||||
|                 .ToListAsync(); |                 .ToListAsync(); | ||||||
|  |  | ||||||
|         if (!tickets.Any()) return; |             if (tickets.Count == 0) | ||||||
|  |             { | ||||||
|  |                 _logger.LogInformation("No pending lottery tickets"); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             _logger.LogInformation("Found {Count} pending lottery tickets for draw", tickets.Count); | ||||||
|  |  | ||||||
|             // Generate winning numbers |             // Generate winning numbers | ||||||
|             var winningRegion1 = GenerateUniqueRandomNumbers(5, 0, 99); |             var winningRegion1 = GenerateUniqueRandomNumbers(5, 0, 99); | ||||||
|             var winningRegion2 = GenerateUniqueRandomNumbers(1, 0, 99)[0]; |             var winningRegion2 = GenerateUniqueRandomNumbers(1, 0, 99)[0]; | ||||||
|  |  | ||||||
|         var drawDate = Instant.FromDateTimeUtc(DateTime.Today.AddDays(-1)); // Yesterday's date |             _logger.LogInformation("Winning numbers generated: Region1 [{Region1}], Region2 [{Region2}]", | ||||||
|  |                 string.Join(",", winningRegion1), winningRegion2); | ||||||
|  |  | ||||||
|  |             var drawDate = Instant.FromDateTimeUtc(new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, | ||||||
|  |                 DateTime.UtcNow.Day, 0, 0, 0, DateTimeKind.Utc).AddDays(-1)); // Yesterday's date | ||||||
|  |  | ||||||
|             var totalPrizesAwarded = 0; |             var totalPrizesAwarded = 0; | ||||||
|             long totalPrizeAmount = 0; |             long totalPrizeAmount = 0; | ||||||
| @@ -170,6 +217,10 @@ public class LotteryService(AppDatabase db, PaymentService paymentService, Walle | |||||||
|                 var region2Match = ticket.RegionTwoNumber == winningRegion2; |                 var region2Match = ticket.RegionTwoNumber == winningRegion2; | ||||||
|                 var reward = CalculateReward(region1Matches, region2Match); |                 var reward = CalculateReward(region1Matches, region2Match); | ||||||
|  |  | ||||||
|  |                 // Record match results | ||||||
|  |                 ticket.MatchedRegionOneNumbers = ticket.RegionOneNumbers.Intersect(winningRegion1).ToList(); | ||||||
|  |                 ticket.MatchedRegionTwoNumber = region2Match ? (int?)winningRegion2 : null; | ||||||
|  |  | ||||||
|                 if (reward > 0) |                 if (reward > 0) | ||||||
|                 { |                 { | ||||||
|                     var wallet = await walletService.GetWalletAsync(ticket.AccountId); |                     var wallet = await walletService.GetWalletAsync(ticket.AccountId); | ||||||
| @@ -178,13 +229,21 @@ public class LotteryService(AppDatabase db, PaymentService paymentService, Walle | |||||||
|                         await paymentService.CreateTransactionAsync( |                         await paymentService.CreateTransactionAsync( | ||||||
|                             payerWalletId: null, |                             payerWalletId: null, | ||||||
|                             payeeWalletId: wallet.Id, |                             payeeWalletId: wallet.Id, | ||||||
|                         currency: "isp", |                             currency: WalletCurrency.SourcePoint, | ||||||
|                             amount: reward, |                             amount: reward, | ||||||
|                             remarks: $"Lottery prize: {region1Matches} matches{(region2Match ? " + special" : "")}" |                             remarks: $"Lottery prize: {region1Matches} matches{(region2Match ? " + special" : "")}" | ||||||
|                         ); |                         ); | ||||||
|  |                         _logger.LogInformation( | ||||||
|  |                             "Awarded {Amount} to account {AccountId} for {Matches} matches{(Special ? \" + special\" : \"\")}", | ||||||
|  |                             reward, ticket.AccountId, region1Matches, region2Match ? " + special" : ""); | ||||||
|                         totalPrizesAwarded++; |                         totalPrizesAwarded++; | ||||||
|                         totalPrizeAmount += reward; |                         totalPrizeAmount += reward; | ||||||
|                     } |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         _logger.LogWarning("Wallet not found for account {AccountId}, skipping prize award", | ||||||
|  |                             ticket.AccountId); | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 ticket.DrawStatus = LotteryDrawStatus.Drawn; |                 ticket.DrawStatus = LotteryDrawStatus.Drawn; | ||||||
| @@ -204,5 +263,14 @@ public class LotteryService(AppDatabase db, PaymentService paymentService, Walle | |||||||
|  |  | ||||||
|             db.LotteryRecords.Add(lotteryRecord); |             db.LotteryRecords.Add(lotteryRecord); | ||||||
|             await db.SaveChangesAsync(); |             await db.SaveChangesAsync(); | ||||||
|  |  | ||||||
|  |             _logger.LogInformation("Daily lottery draw completed: {Prizes} prizes awarded, total amount {Amount}", | ||||||
|  |                 totalPrizesAwarded, totalPrizeAmount); | ||||||
|  |         } | ||||||
|  |         catch (Exception ex) | ||||||
|  |         { | ||||||
|  |             _logger.LogError(ex, "An error occurred during the daily lottery draw"); | ||||||
|  |             throw; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
							
								
								
									
										2620
									
								
								DysonNetwork.Pass/Migrations/20251024154539_AddDetailLotteriesStatus.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										2620
									
								
								DysonNetwork.Pass/Migrations/20251024154539_AddDetailLotteriesStatus.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | using System.Collections.Generic; | ||||||
|  | using Microsoft.EntityFrameworkCore.Migrations; | ||||||
|  |  | ||||||
|  | #nullable disable | ||||||
|  |  | ||||||
|  | namespace DysonNetwork.Pass.Migrations | ||||||
|  | { | ||||||
|  |     /// <inheritdoc /> | ||||||
|  |     public partial class AddDetailLotteriesStatus : Migration | ||||||
|  |     { | ||||||
|  |         /// <inheritdoc /> | ||||||
|  |         protected override void Up(MigrationBuilder migrationBuilder) | ||||||
|  |         { | ||||||
|  |             migrationBuilder.AddColumn<List<int>>( | ||||||
|  |                 name: "matched_region_one_numbers", | ||||||
|  |                 table: "lotteries", | ||||||
|  |                 type: "jsonb", | ||||||
|  |                 nullable: true); | ||||||
|  |  | ||||||
|  |             migrationBuilder.AddColumn<int>( | ||||||
|  |                 name: "matched_region_two_number", | ||||||
|  |                 table: "lotteries", | ||||||
|  |                 type: "integer", | ||||||
|  |                 nullable: true); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <inheritdoc /> | ||||||
|  |         protected override void Down(MigrationBuilder migrationBuilder) | ||||||
|  |         { | ||||||
|  |             migrationBuilder.DropColumn( | ||||||
|  |                 name: "matched_region_one_numbers", | ||||||
|  |                 table: "lotteries"); | ||||||
|  |  | ||||||
|  |             migrationBuilder.DropColumn( | ||||||
|  |                 name: "matched_region_two_number", | ||||||
|  |                 table: "lotteries"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1086,6 +1086,14 @@ namespace DysonNetwork.Pass.Migrations | |||||||
|                         .HasColumnType("integer") |                         .HasColumnType("integer") | ||||||
|                         .HasColumnName("draw_status"); |                         .HasColumnName("draw_status"); | ||||||
|  |  | ||||||
|  |                     b.Property<List<int>>("MatchedRegionOneNumbers") | ||||||
|  |                         .HasColumnType("jsonb") | ||||||
|  |                         .HasColumnName("matched_region_one_numbers"); | ||||||
|  |  | ||||||
|  |                     b.Property<int?>("MatchedRegionTwoNumber") | ||||||
|  |                         .HasColumnType("integer") | ||||||
|  |                         .HasColumnName("matched_region_two_number"); | ||||||
|  |  | ||||||
|                     b.Property<int>("Multiplier") |                     b.Property<int>("Multiplier") | ||||||
|                         .HasColumnType("integer") |                         .HasColumnType("integer") | ||||||
|                         .HasColumnName("multiplier"); |                         .HasColumnName("multiplier"); | ||||||
|   | |||||||
| @@ -30,20 +30,25 @@ public class SnLotteryRecord : ModelBase | |||||||
|  |  | ||||||
| public class SnLottery : ModelBase | public class SnLottery : ModelBase | ||||||
| { | { | ||||||
|     public Guid Id { get; set; } = Guid.NewGuid(); |     public Guid Id { get; init; } = Guid.NewGuid(); | ||||||
|  |  | ||||||
|     public SnAccount Account { get; set; } = null!; |     public SnAccount Account { get; init; } = null!; | ||||||
|     public Guid AccountId { get; set; } |     public Guid AccountId { get; init; } | ||||||
|  |  | ||||||
|     [Column(TypeName = "jsonb")] |     [Column(TypeName = "jsonb")] | ||||||
|     public List<int> RegionOneNumbers { get; set; } = new(); // 5 numbers, 0-99, unique |     public List<int> RegionOneNumbers { get; set; } = []; // 5 numbers, 0-99, unique | ||||||
|  |  | ||||||
|     [Range(0, 99)] |     [Range(0, 99)] | ||||||
|     public int RegionTwoNumber { get; set; } // 1 number, 0-99, can repeat |     public int RegionTwoNumber { get; init; } // 1 number, 0-99, can repeat | ||||||
|  |  | ||||||
|     public int Multiplier { get; set; } = 1; // Default 1x |     public int Multiplier { get; init; } = 1; // Default 1x | ||||||
|  |  | ||||||
|     public LotteryDrawStatus DrawStatus { get; set; } = LotteryDrawStatus.Pending; // Status to track draw processing |     public LotteryDrawStatus DrawStatus { get; set; } = LotteryDrawStatus.Pending; // Status to track draw processing | ||||||
|  |  | ||||||
|     public Instant? DrawDate { get; set; } // Date when this ticket was drawn |     public Instant? DrawDate { get; set; } // Date when this ticket was drawn | ||||||
|  |  | ||||||
|  |     [Column(TypeName = "jsonb")] | ||||||
|  |     public List<int>? MatchedRegionOneNumbers { get; set; } // The actual numbers that matched in region one | ||||||
|  |  | ||||||
|  |     public int? MatchedRegionTwoNumber { get; set; } // The matched number if special number matched (null otherwise) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -93,7 +93,7 @@ public class BroadcastEventHandler( | |||||||
|                             break; |                             break; | ||||||
|                         } |                         } | ||||||
|                     default: |                     default: | ||||||
|                         await msg.NakAsync(cancellationToken: stoppingToken); |                         // ignore | ||||||
|                         break; |                         break; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user