diff --git a/KfChatDotNetBot/ApplicationDbContext.cs b/KfChatDotNetBot/ApplicationDbContext.cs index 1da2ce4..69cbde3 100644 --- a/KfChatDotNetBot/ApplicationDbContext.cs +++ b/KfChatDotNetBot/ApplicationDbContext.cs @@ -15,4 +15,5 @@ public class ApplicationDbContext : DbContext public DbSet Settings { get; set; } public DbSet HowlggBets { get; set; } public DbSet RainbetBets { get; set; } + public DbSet TwitchViewCounts { get; set; } } \ No newline at end of file diff --git a/KfChatDotNetBot/Migrations/20240815041430_TwitchViews.Designer.cs b/KfChatDotNetBot/Migrations/20240815041430_TwitchViews.Designer.cs new file mode 100644 index 0000000..4cd5c60 --- /dev/null +++ b/KfChatDotNetBot/Migrations/20240815041430_TwitchViews.Designer.cs @@ -0,0 +1,211 @@ +// +using System; +using KfChatDotNetBot; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace KfChatDotNetBot.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240815041430_TwitchViews")] + partial class TwitchViews + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.7"); + + modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.HowlggBetsDbModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Bet") + .HasColumnType("INTEGER"); + + b.Property("BetId") + .HasColumnType("INTEGER"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("Game") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("GameId") + .HasColumnType("INTEGER"); + + b.Property("Profit") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("HowlggBets"); + }); + + modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.JuicerDbModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("REAL"); + + b.Property("JuicedAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Juicers"); + }); + + modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.RainbetBetsDbModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("BetId") + .HasColumnType("INTEGER"); + + b.Property("BetSeenAt") + .HasColumnType("TEXT"); + + b.Property("GameName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Multiplier") + .HasColumnType("REAL"); + + b.Property("Payout") + .HasColumnType("REAL"); + + b.Property("PublicId") + .HasColumnType("TEXT"); + + b.Property("RainbetUserId") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("REAL"); + + b.HasKey("Id"); + + b.ToTable("RainbetBets"); + }); + + modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.SettingDbModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Default") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("IsSecret") + .HasColumnType("INTEGER"); + + b.Property("Key") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Regex") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Settings"); + }); + + modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.TwitchViewCountDbModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ServerTime") + .HasColumnType("REAL"); + + b.Property("Time") + .HasColumnType("TEXT"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Viewers") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TwitchViewCounts"); + }); + + modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.UserDbModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Ignored") + .HasColumnType("INTEGER"); + + b.Property("KfId") + .HasColumnType("INTEGER"); + + b.Property("KfUsername") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UserRight") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.JuicerDbModel", b => + { + b.HasOne("KfChatDotNetBot.Models.DbModels.UserDbModel", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/KfChatDotNetBot/Migrations/20240815041430_TwitchViews.cs b/KfChatDotNetBot/Migrations/20240815041430_TwitchViews.cs new file mode 100644 index 0000000..0137b52 --- /dev/null +++ b/KfChatDotNetBot/Migrations/20240815041430_TwitchViews.cs @@ -0,0 +1,38 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace KfChatDotNetBot.Migrations +{ + /// + public partial class TwitchViews : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "TwitchViewCounts", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Topic = table.Column(type: "TEXT", nullable: false), + ServerTime = table.Column(type: "REAL", nullable: false), + Viewers = table.Column(type: "INTEGER", nullable: false), + Time = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_TwitchViewCounts", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "TwitchViewCounts"); + } + } +} diff --git a/KfChatDotNetBot/Migrations/ApplicationDbContextModelSnapshot.cs b/KfChatDotNetBot/Migrations/ApplicationDbContextModelSnapshot.cs index a1f76f6..6cee739 100644 --- a/KfChatDotNetBot/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/KfChatDotNetBot/Migrations/ApplicationDbContextModelSnapshot.cs @@ -144,6 +144,30 @@ namespace KfChatDotNetBot.Migrations b.ToTable("Settings"); }); + modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.TwitchViewCountDbModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ServerTime") + .HasColumnType("REAL"); + + b.Property("Time") + .HasColumnType("TEXT"); + + b.Property("Topic") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Viewers") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TwitchViewCounts"); + }); + modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.UserDbModel", b => { b.Property("Id") diff --git a/KfChatDotNetBot/Models/DbModels/TwitchViewCountDbModel.cs b/KfChatDotNetBot/Models/DbModels/TwitchViewCountDbModel.cs new file mode 100644 index 0000000..81e80b3 --- /dev/null +++ b/KfChatDotNetBot/Models/DbModels/TwitchViewCountDbModel.cs @@ -0,0 +1,10 @@ +namespace KfChatDotNetBot.Models.DbModels; + +public class TwitchViewCountDbModel +{ + public int Id { get; set; } + public required string Topic { get; set; } + public required double ServerTime { get; set; } + public required int Viewers { get; set; } + public required DateTimeOffset Time { get; set; } +} \ No newline at end of file diff --git a/KfChatDotNetBot/Services/Twitch.cs b/KfChatDotNetBot/Services/Twitch.cs index 99d3430..bc4876b 100644 --- a/KfChatDotNetBot/Services/Twitch.cs +++ b/KfChatDotNetBot/Services/Twitch.cs @@ -2,6 +2,7 @@ using System.Net.Http.Json; using System.Net.WebSockets; using System.Text.Json; +using KfChatDotNetBot.Models.DbModels; using NLog; using Websocket.Client; @@ -132,19 +133,34 @@ public class Twitch : IDisposable return; var topicParts = topicString.Split('.'); var channelId = int.Parse(topicParts[^1]); - var twitchMessage = data.GetProperty("message")!.GetString()!; + var twitchMessage = JsonSerializer.Deserialize(data.GetProperty("message").GetString()); - if (twitchMessage.Contains("\"type\":\"stream-up\"")) + if (twitchMessage.GetProperty("type").GetString() == "stream-up") { OnStreamStateUpdated?.Invoke(this, channelId, true); return; } - if (twitchMessage.Contains("\"type\":\"stream-down\"")) + if (twitchMessage.GetProperty("type").GetString() == "stream-down") { OnStreamStateUpdated?.Invoke(this, channelId, false); return; } + + if (twitchMessage.GetProperty("type").GetString() == "viewcount") + { + _logger.Info("Updating DB with fresh view count"); + using var db = new ApplicationDbContext(); + db.TwitchViewCounts.Add(new TwitchViewCountDbModel + { + Topic = topicString, + ServerTime = twitchMessage.GetProperty("server_time").GetDouble(), + Viewers = twitchMessage.GetProperty("viewers").GetInt32(), + Time = DateTimeOffset.UtcNow + }); + db.SaveChanges(); + return; + } _logger.Info("Message from Twitch was unhandled"); _logger.Info(message.Text); }