mirror of
https://github.com/barelyprofessional/KfChatDotNet.git
synced 2026-05-11 08:39:34 -04:00
Updated the tagging code from cohle
- Uses a List<string> as the underlying type which EF Core will serialize as JSON. Since SQLite doesn't have any native JSON features, it gets stored as TEXT - Got rid of the alternate pathway used for selecting an image so it always has a degree of randomness assuming enough images were returned - Simplified some of the existing Regex and removed the non capturing groups as they're cancerous - Added/removed images will be spoilered. - Added a metadata property for images. This is a JSON object that EF Core will serialize/deserialize for you and presently contains the user ID of whoever added the image as well as when it was added. Can be easily extended with no migration needed. Will be null for existing images. - Added a migration process for moving Tags to TagList for fishtank
This commit is contained in:
@@ -14,6 +14,8 @@ public class ApplicationDbContext : DbContext
|
||||
{
|
||||
//modelBuilder.Entity<KasinoShopProfileDbModel>()
|
||||
// .OwnsOne(p => p.StateData, b => b.ToJson());
|
||||
modelBuilder.Entity<ImageDbModel>().
|
||||
OwnsOne(p => p.Metadata, b => b.ToJson());
|
||||
}
|
||||
|
||||
public DbSet<UserDbModel> Users { get; set; }
|
||||
|
||||
@@ -7,21 +7,18 @@ using KfChatDotNetBot.Models;
|
||||
using KfChatDotNetBot.Models.DbModels;
|
||||
using KfChatDotNetBot.Services;
|
||||
using KfChatDotNetBot.Settings;
|
||||
using KfChatDotNetWsClient.Models.Events;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NLog;
|
||||
|
||||
namespace KfChatDotNetBot.Commands;
|
||||
|
||||
public class AddImageCommand : ICommand
|
||||
{
|
||||
public List<Regex> Patterns => [
|
||||
new Regex(@"^admin image (?<key>\w+) add (?<url>\S+)(?:\s+(?<raw>raw))?(?:\s+(?<tags>.+))?$"),
|
||||
new Regex(@"^admin images (?<key>\w+) add (?<url>\S+)(?:\s+(?<raw>raw))?(?:\s+(?<tags>.+))?$"),
|
||||
new Regex(@"^admin image (?<key>\w+) add_nigger (?<url>\S+)(?:\s+(?<raw>raw))?(?:\s+(?<tags>.+))?$"),
|
||||
new Regex(@"^admin images (?<key>\w+) add_nigger (?<url>\S+)(?:\s+(?<raw>raw))?(?:\s+(?<tags>.+))?$")
|
||||
new Regex(@"^admin (image|images) (?<key>\w+) (add|add_nigger) (?<url>\S+) (?<raw>raw) (?<tags>.+)$", RegexOptions.IgnoreCase),
|
||||
new Regex(@"^admin (image|images) (?<key>\w+) (add|add_nigger) (?<url>\S+) (?<tags>.+)$", RegexOptions.IgnoreCase),
|
||||
new Regex(@"^admin (image|images) (?<key>\w+) (add|add_nigger) (?<url>\S+)$", RegexOptions.IgnoreCase)
|
||||
];
|
||||
public string? HelpText => "Add an image to the image rotation specified";
|
||||
public string HelpText => "Add an image to the image rotation specified";
|
||||
public UserRight RequiredRight => UserRight.TrueAndHonest;
|
||||
public TimeSpan Timeout => TimeSpan.FromSeconds(10);
|
||||
public RateLimitOptionsModel? RateLimitOptions => null;
|
||||
@@ -34,13 +31,14 @@ public class AddImageCommand : ICommand
|
||||
if (imageKeys == null) throw new InvalidOperationException($"{BuiltIn.Keys.BotImageAcceptableKeys} was null");
|
||||
var key = arguments["key"].Value;
|
||||
var url = arguments["url"].Value;
|
||||
var tags = arguments["tags"].Success ? arguments["tags"].Value.Trim() : null;
|
||||
var tags = arguments.TryGetValue("tags", out var tagsArg) ? tagsArg.Value.ToLower().Split(" ").ToList() : [];
|
||||
var niggerMode = message.Message.Contains("add_nigger");
|
||||
var _rawMode = arguments["raw"].Success;
|
||||
// TODO: Implement real and raw mode
|
||||
//var _rawMode = arguments.ContainsKey("raw");
|
||||
if (!imageKeys.Contains(key))
|
||||
{
|
||||
await botInstance.SendChatMessageAsync(
|
||||
$"Key you specified is not supported. Available keys are: {string.Join(' ', imageKeys)}", true);
|
||||
$"Key you specified is not supported. Available keys are: {imageKeys.Humanize()}", true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -49,32 +47,34 @@ public class AddImageCommand : ICommand
|
||||
await botInstance.SendChatMessageAsync("This image already exists in the database with this key", true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Regex.IsMatch(url, @"^https?://\S+$"))
|
||||
|
||||
if (!Uri.TryCreate(url, UriKind.Absolute, out _))
|
||||
{
|
||||
await botInstance.SendWhisperAsync(user.KfId, $"The URL '{url}' you provided is not valid");
|
||||
return;
|
||||
}
|
||||
|
||||
string result = url;
|
||||
var result = url;
|
||||
// todo add automatic compression/re-upload and raw mode option
|
||||
|
||||
await db.Images.AddAsync(new ImageDbModel { Key = key, Url = result, LastSeen = DateTimeOffset.MinValue, Tags = tags }, ctx);
|
||||
await db.Images.AddAsync(new ImageDbModel
|
||||
{
|
||||
Key = key, Url = result, LastSeen = DateTimeOffset.MinValue, TagList = tags,
|
||||
Metadata = new ImageMetadataModel { AddedByUserId = user.Id, WhenAdded = DateTimeOffset.UtcNow }
|
||||
}, ctx);
|
||||
var count = await db.Images.CountAsync(cancellationToken: ctx);
|
||||
await db.SaveChangesAsync(ctx);
|
||||
await botInstance.SendChatMessageAsync(
|
||||
$"{user.FormatUsername()}, you added the following media to the {key} carousel\n[img]{url}[/img]", true);
|
||||
$"{user.FormatUsername()}, you added the following media to the {key} carousel which now has {count:N0} images[spoiler=\"Image\"][img]{url}[/img]", true);
|
||||
}
|
||||
}
|
||||
|
||||
public class RemoveImageCommand : ICommand
|
||||
{
|
||||
public List<Regex> Patterns => [
|
||||
new Regex(@"^admin image (?<key>\w+) remove (?<url>.+)$"),
|
||||
new Regex(@"^admin images (?<key>\w+) remove (?<url>.+)$"),
|
||||
new Regex(@"^admin image (?<key>\w+) delete (?<url>.+)$"),
|
||||
new Regex(@"^admin images (?<key>\w+) delete (?<url>.+)$")
|
||||
new Regex(@"^admin (image|images) (?<key>\w+) (remove|delete) (?<url>.+)$"),
|
||||
];
|
||||
public string? HelpText => "Remove an image from the image rotation specified";
|
||||
public string HelpText => "Remove an image from the image rotation specified";
|
||||
public UserRight RequiredRight => UserRight.TrueAndHonest;
|
||||
public TimeSpan Timeout => TimeSpan.FromSeconds(10);
|
||||
public RateLimitOptionsModel? RateLimitOptions => null;
|
||||
@@ -103,22 +103,25 @@ public class RemoveImageCommand : ICommand
|
||||
|
||||
db.Images.Remove(image);
|
||||
await db.SaveChangesAsync(ctx);
|
||||
// await botInstance.SendChatMessageAsync("Removed image from database", true);
|
||||
await botInstance.SendChatMessageAsync(
|
||||
$"{user.FormatUsername()}, you removed the following media from the {key} carousel\n[img]{url}[/img]", true);
|
||||
$"{user.FormatUsername()}, you removed the following media from the {key} carousel[spoiler=\"Image\"][img]{url}[/img]", true);
|
||||
}
|
||||
}
|
||||
|
||||
public class ListImageCommand : ICommand
|
||||
{
|
||||
public List<Regex> Patterns => [
|
||||
new Regex(@"^admin image (?<key>\w+) list$"),
|
||||
new Regex(@"^admin images (?<key>\w+) list$")
|
||||
new Regex(@"^admin (image|images) (?<key>\w+) list$"),
|
||||
];
|
||||
public string? HelpText => "Remove an image from the image rotation specified";
|
||||
public UserRight RequiredRight => UserRight.TrueAndHonest;
|
||||
public string HelpText => "List images for a given carousel";
|
||||
public UserRight RequiredRight => UserRight.Guest;
|
||||
public TimeSpan Timeout => TimeSpan.FromSeconds(10);
|
||||
public RateLimitOptionsModel? RateLimitOptions => null;
|
||||
public RateLimitOptionsModel RateLimitOptions => new()
|
||||
{
|
||||
Flags = RateLimitFlags.None,
|
||||
MaxInvocations = 2,
|
||||
Window = TimeSpan.FromSeconds(15)
|
||||
};
|
||||
public bool WhisperCanInvoke => false;
|
||||
public async Task RunCommand(ChatBot botInstance, BotCommandMessageModel message, UserDbModel user, GroupCollection arguments,
|
||||
CancellationToken ctx)
|
||||
@@ -131,19 +134,19 @@ public class ListImageCommand : ICommand
|
||||
if (!imageKeys.Contains(key))
|
||||
{
|
||||
await botInstance.SendChatMessageAsync(
|
||||
$"Key you specified is not supported. Available keys are: {string.Join(' ', imageKeys)}", true);
|
||||
$"Key you specified is not supported. Available keys are: {imageKeys.Humanize()}", true);
|
||||
return;
|
||||
}
|
||||
|
||||
var images = db.Images.Where(i => i.Key == key);
|
||||
if (await images.CountAsync(cancellationToken: ctx) > 20 && await Zipline.IsZiplineEnabled())
|
||||
if (await images.CountAsync(cancellationToken: ctx) > 10 && await Zipline.IsZiplineEnabled())
|
||||
{
|
||||
var content = string.Empty;
|
||||
foreach (var image in images)
|
||||
{
|
||||
var ts = DateTimeOffset.UtcNow - image.LastSeen;
|
||||
var time = $"{ts.TotalDays:N0}d{ts.Hours:N0}h{ts.Minutes:N0}m{ts.Seconds:N0}s";
|
||||
content += $"{image.Url} - {time} - {image.Tags}" + Environment.NewLine;
|
||||
content += $"{image.Url} - {time} - {image.TagList.Humanize(" ")}" + Environment.NewLine;
|
||||
}
|
||||
|
||||
var paste = await Zipline.Upload(content, new MediaTypeHeaderValue("text/plain"), "1d", ctx);
|
||||
@@ -168,51 +171,51 @@ public class ListImageCommand : ICommand
|
||||
public class ManageImageKeyCommand : ICommand
|
||||
{
|
||||
public List<Regex> Patterns => [
|
||||
new Regex(@"^admin imagekey add (?<key>\w+)$"),
|
||||
new Regex(@"^admin imagekey remove (?<key>\w+)$"),
|
||||
new Regex(@"^admin imagekey delete (?<key>\w+)$"),
|
||||
new Regex(@"^admin imageskey add (?<key>\w+)$"),
|
||||
new Regex(@"^admin imageskey remove (?<key>\w+)$"),
|
||||
new Regex(@"^admin imageskey delete (?<key>\w+)$")
|
||||
new Regex(@"^admin (imagekey|imageskey) (?<operation>add|remove|delete) (?<key>\w+)$"),
|
||||
];
|
||||
public string? HelpText => "Add or remove an acceptable image key from the BotImageAcceptableKeys setting";
|
||||
public string HelpText => "Add or remove an acceptable image key from the BotImageAcceptableKeys setting";
|
||||
public UserRight RequiredRight => UserRight.Admin;
|
||||
public TimeSpan Timeout => TimeSpan.FromSeconds(10);
|
||||
public RateLimitOptionsModel? RateLimitOptions => null;
|
||||
public bool WhisperCanInvoke => false;
|
||||
public bool WhisperCanInvoke => true;
|
||||
public async Task RunCommand(ChatBot botInstance, BotCommandMessageModel message, UserDbModel user, GroupCollection arguments,
|
||||
CancellationToken ctx)
|
||||
{
|
||||
var imageKeys = (await SettingsProvider.GetValueAsync(BuiltIn.Keys.BotImageAcceptableKeys)).JsonDeserialize<List<string>>();
|
||||
if (imageKeys == null) throw new InvalidOperationException($"{BuiltIn.Keys.BotImageAcceptableKeys} was null");
|
||||
var key = arguments["key"].Value.ToLower();
|
||||
var isAdd = message.Message.Contains(" add ");
|
||||
var operation = arguments["operation"].Value.ToLower();
|
||||
|
||||
if (isAdd)
|
||||
if (operation is "add")
|
||||
{
|
||||
if (imageKeys.Contains(key))
|
||||
{
|
||||
await botInstance.SendChatMessageAsync($"Key \"{key}\" is already in the acceptable keys list", true);
|
||||
await botInstance.ReplyToUser(message, $"Key \"{key}\" is already in the acceptable keys list", true);
|
||||
return;
|
||||
}
|
||||
imageKeys.Add(key);
|
||||
await SettingsProvider.SetValueAsync(BuiltIn.Keys.BotImageAcceptableKeys, JsonSerializer.Serialize(imageKeys));
|
||||
await botInstance.SendChatMessageAsync(
|
||||
$"Added key \"{key}\" to acceptable image keys. Current keys: {string.Join(' ', imageKeys)}", true);
|
||||
await botInstance.ReplyToUser(message,
|
||||
$"Added key \"{key}\" to acceptable image keys. Current keys: {imageKeys.Humanize()}", true);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
if (operation is "remove" or "delete")
|
||||
{
|
||||
if (!imageKeys.Contains(key))
|
||||
{
|
||||
await botInstance.SendChatMessageAsync(
|
||||
$"Key \"{key}\" is not in the acceptable keys list. Current keys: {string.Join(' ', imageKeys)}", true);
|
||||
await botInstance.ReplyToUser(message,
|
||||
$"Key \"{key}\" is not in the acceptable keys list. Current keys: {imageKeys.Humanize()}", true);
|
||||
return;
|
||||
}
|
||||
imageKeys.Remove(key);
|
||||
await SettingsProvider.SetValueAsync(BuiltIn.Keys.BotImageAcceptableKeys, JsonSerializer.Serialize(imageKeys));
|
||||
await botInstance.SendChatMessageAsync(
|
||||
$"Removed key \"{key}\" from acceptable image keys. Current keys: {string.Join(' ', imageKeys)}", true);
|
||||
await botInstance.ReplyToUser(message,
|
||||
$"Removed key \"{key}\" from acceptable image keys. Current keys: {imageKeys.Humanize()}", true);
|
||||
return;
|
||||
}
|
||||
|
||||
await botInstance.ReplyToUser(message, $"Operation '{operation}' not supported", true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,12 +223,13 @@ public class ManageImageKeyCommand : ICommand
|
||||
public class GetRandomImage : ICommand
|
||||
{
|
||||
public List<Regex> Patterns => [
|
||||
new Regex(@"^(?<key>\w+)(?:\s+(?<search>.+))?")
|
||||
new Regex(@"^(?<key>\w+)$"),
|
||||
new Regex(@"^(?<key>\w+) (?<search>.+)")
|
||||
];
|
||||
public string? HelpText => "Get a random image";
|
||||
public string HelpText => "Get a random image";
|
||||
public UserRight RequiredRight => UserRight.Loser;
|
||||
public TimeSpan Timeout => TimeSpan.FromMinutes(10);
|
||||
public RateLimitOptionsModel? RateLimitOptions => new()
|
||||
public RateLimitOptionsModel RateLimitOptions => new()
|
||||
{
|
||||
Window = TimeSpan.FromSeconds(30),
|
||||
MaxInvocations = 7,
|
||||
@@ -237,7 +241,7 @@ public class GetRandomImage : ICommand
|
||||
{
|
||||
await using var db = new ApplicationDbContext();
|
||||
var key = arguments["key"].Value.ToLower();
|
||||
var searchTerm = arguments["search"].Success ? arguments["search"].Value.Trim() : null;
|
||||
var searchTerm = arguments.TryGetValue("search", out var searchArg) ? searchArg.Value.ToLower().Trim() : null;
|
||||
var images = db.Images.Where(i => i.Key == key);
|
||||
if (!await images.AnyAsync(ctx))
|
||||
{
|
||||
@@ -257,40 +261,31 @@ public class GetRandomImage : ICommand
|
||||
BuiltIn.Keys.BotImageChinkSelfDestruct, BuiltIn.Keys.BotImageChinkSelfDestructDelay
|
||||
]);
|
||||
|
||||
ImageDbModel image;
|
||||
var selection = await images.ToListAsync(ctx);
|
||||
if (!string.IsNullOrEmpty(searchTerm))
|
||||
{
|
||||
var allImages = await images.ToListAsync(ctx);
|
||||
var searchTokens = searchTerm.ToLower().Split(' ', StringSplitOptions.RemoveEmptyEntries);
|
||||
var matches = allImages.Where(i =>
|
||||
{
|
||||
if (i.Tags == null) return false;
|
||||
var tagTokens = i.Tags.ToLower().Split(' ', StringSplitOptions.RemoveEmptyEntries);
|
||||
return searchTokens.All(st => tagTokens.Contains(st));
|
||||
}).ToList();
|
||||
if (matches.Count == 0)
|
||||
selection = searchTokens.Aggregate(selection, (current, token) =>
|
||||
current.Where(i => i.TagList.Count > 0 && i.TagList.Contains(token)).ToList());
|
||||
if (selection.Count == 0)
|
||||
{
|
||||
RateLimitService.RemoveMostRecentEntry(user, this);
|
||||
await botInstance.SendChatMessageAsync($"No image in {key} matched \"{searchTerm}\"", true);
|
||||
return;
|
||||
}
|
||||
image = matches.OrderBy(i => i.LastSeen).First();
|
||||
}
|
||||
else
|
||||
var divideBy = settings[BuiltIn.Keys.BotImageRandomSliceDivideBy].ToType<int>();
|
||||
var limit = 1;
|
||||
var count = await images.CountAsync(ctx);
|
||||
if (count > divideBy)
|
||||
{
|
||||
var divideBy = settings[BuiltIn.Keys.BotImageRandomSliceDivideBy].ToType<int>();
|
||||
var limit = 1;
|
||||
var count = await images.CountAsync(ctx);
|
||||
if (count > divideBy)
|
||||
{
|
||||
limit = count / divideBy;
|
||||
}
|
||||
|
||||
// EF with SQLite can't sort on dates as it's just TEXT
|
||||
var selection = (await images.ToListAsync(ctx)).OrderBy(i => i.LastSeen).Take(limit).ToList();
|
||||
// MaxValue is never returned by Next so you don't need to -1 for indexing
|
||||
image = selection[new Random().Next(0, selection.Count)];
|
||||
limit = count / divideBy;
|
||||
}
|
||||
|
||||
// EF with SQLite can't sort on dates as it's just TEXT
|
||||
selection = selection.OrderBy(i => i.LastSeen).Take(limit).ToList();
|
||||
// MaxValue is never returned by Next so you don't need to -1 for indexing
|
||||
var image = selection[new Random().Next(0, selection.Count)];
|
||||
image.LastSeen = DateTimeOffset.UtcNow;
|
||||
db.Images.Update(image);
|
||||
await db.SaveChangesAsync(ctx);
|
||||
|
||||
640
KfChatDotNetBot/Migrations/20260510172529_ImageTagList.Designer.cs
generated
Normal file
640
KfChatDotNetBot/Migrations/20260510172529_ImageTagList.Designer.cs
generated
Normal file
@@ -0,0 +1,640 @@
|
||||
// <auto-generated />
|
||||
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("20260510172529_ImageTagList")]
|
||||
partial class ImageTagList
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "10.0.3");
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.ChipsggBetDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<double>("Amount")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<string>("BetId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Currency")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<float>("CurrencyPrice")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<string>("GameTitle")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<float>("Multiplier")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<DateTimeOffset>("Updated")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Win")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<double>("Winnings")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("ChipsggBets");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.GamblerDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<decimal>("Balance")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<decimal>("NextVipLevelWagerRequirement")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("RandomSeed")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("State")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<decimal>("TotalWagered")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Gamblers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.GamblerExclusionDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("Expires")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("GamblerId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Source")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GamblerId");
|
||||
|
||||
b.ToTable("Exclusions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.GamblerPerkDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("GamblerId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Metadata")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<decimal?>("Payout")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("PerkName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("PerkTier")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("PerkType")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset>("Time")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GamblerId");
|
||||
|
||||
b.ToTable("Perks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.HowlggBetsDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<long>("Bet")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("BetId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset>("Date")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Game")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long>("GameId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<long>("Profit")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("HowlggBets");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.ImageDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("LastSeen")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.PrimitiveCollection<string>("TagList")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Tags")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Url")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Images");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.JuicerDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<float>("Amount")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<DateTimeOffset>("JuicedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Juicers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.MomDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset>("Time")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Moms");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.RainbetBetsDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("BetId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("BetSeenAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("GameName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<float>("Multiplier")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<float>("Payout")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<string>("PublicId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("RainbetUserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<float>("Value")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("RainbetBets");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.SettingDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<double>("CacheDuration")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<string>("Default")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("IsSecret")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Regex")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("ValueType")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Settings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.StreamDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("AutoCapture")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Metadata")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Service")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("StreamUrl")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Streams");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.TransactionDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Comment")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<decimal>("Effect")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("EventSource")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("FromId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("GamblerId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<decimal>("NewBalance")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("Time")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long>("TimeUnixEpochSeconds")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("FromId");
|
||||
|
||||
b.HasIndex("GamblerId");
|
||||
|
||||
b.ToTable("Transactions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.TwitchViewCountDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<double>("ServerTime")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<DateTimeOffset>("Time")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Topic")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Viewers")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("TwitchViewCounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.UserDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("Ignored")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("KfId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("KfUsername")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("UserRight")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.UserWhoWasDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ActivityType")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset>("FirstOccurence")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("LatestOccurence")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("UsersWhoWere");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.WagerDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("GamblerId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Game")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("GameMeta")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("IsComplete")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<decimal>("Multiplier")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("Time")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long>("TimeUnixEpochSeconds")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<decimal>("WagerAmount")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<decimal>("WagerEffect")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GamblerId");
|
||||
|
||||
b.ToTable("Wagers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.GamblerDbModel", b =>
|
||||
{
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.UserDbModel", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.GamblerExclusionDbModel", b =>
|
||||
{
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.GamblerDbModel", "Gambler")
|
||||
.WithMany()
|
||||
.HasForeignKey("GamblerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Gambler");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.GamblerPerkDbModel", b =>
|
||||
{
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.GamblerDbModel", "Gambler")
|
||||
.WithMany()
|
||||
.HasForeignKey("GamblerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Gambler");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.JuicerDbModel", b =>
|
||||
{
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.UserDbModel", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.MomDbModel", b =>
|
||||
{
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.UserDbModel", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.StreamDbModel", b =>
|
||||
{
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.UserDbModel", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.TransactionDbModel", b =>
|
||||
{
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.GamblerDbModel", "From")
|
||||
.WithMany()
|
||||
.HasForeignKey("FromId");
|
||||
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.GamblerDbModel", "Gambler")
|
||||
.WithMany()
|
||||
.HasForeignKey("GamblerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("From");
|
||||
|
||||
b.Navigation("Gambler");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.UserWhoWasDbModel", b =>
|
||||
{
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.UserDbModel", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.WagerDbModel", b =>
|
||||
{
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.GamblerDbModel", "Gambler")
|
||||
.WithMany()
|
||||
.HasForeignKey("GamblerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Gambler");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
29
KfChatDotNetBot/Migrations/20260510172529_ImageTagList.cs
Normal file
29
KfChatDotNetBot/Migrations/20260510172529_ImageTagList.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace KfChatDotNetBot.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class ImageTagList : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "TagList",
|
||||
table: "Images",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: "[]");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "TagList",
|
||||
table: "Images");
|
||||
}
|
||||
}
|
||||
}
|
||||
665
KfChatDotNetBot/Migrations/20260510194844_ImageMetadata.Designer.cs
generated
Normal file
665
KfChatDotNetBot/Migrations/20260510194844_ImageMetadata.Designer.cs
generated
Normal file
@@ -0,0 +1,665 @@
|
||||
// <auto-generated />
|
||||
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("20260510194844_ImageMetadata")]
|
||||
partial class ImageMetadata
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "10.0.3");
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.ChipsggBetDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<double>("Amount")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<string>("BetId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Currency")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<float>("CurrencyPrice")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<string>("GameTitle")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<float>("Multiplier")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<DateTimeOffset>("Updated")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Win")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<double>("Winnings")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("ChipsggBets");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.GamblerDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<decimal>("Balance")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<decimal>("NextVipLevelWagerRequirement")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("RandomSeed")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("State")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<decimal>("TotalWagered")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Gamblers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.GamblerExclusionDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("Expires")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("GamblerId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Source")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GamblerId");
|
||||
|
||||
b.ToTable("Exclusions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.GamblerPerkDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("GamblerId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Metadata")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<decimal?>("Payout")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("PerkName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("PerkTier")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("PerkType")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset>("Time")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GamblerId");
|
||||
|
||||
b.ToTable("Perks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.HowlggBetsDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<long>("Bet")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("BetId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset>("Date")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Game")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long>("GameId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<long>("Profit")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("HowlggBets");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.ImageDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("LastSeen")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.PrimitiveCollection<string>("TagList")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Tags")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Url")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Images");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.JuicerDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<float>("Amount")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<DateTimeOffset>("JuicedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Juicers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.MomDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset>("Time")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Moms");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.RainbetBetsDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("BetId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("BetSeenAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("GameName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<float>("Multiplier")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<float>("Payout")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<string>("PublicId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("RainbetUserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<float>("Value")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("RainbetBets");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.SettingDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<double>("CacheDuration")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<string>("Default")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("IsSecret")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Regex")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("ValueType")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Settings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.StreamDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("AutoCapture")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Metadata")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Service")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("StreamUrl")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Streams");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.TransactionDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Comment")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<decimal>("Effect")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("EventSource")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("FromId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("GamblerId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<decimal>("NewBalance")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("Time")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long>("TimeUnixEpochSeconds")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("FromId");
|
||||
|
||||
b.HasIndex("GamblerId");
|
||||
|
||||
b.ToTable("Transactions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.TwitchViewCountDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<double>("ServerTime")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<DateTimeOffset>("Time")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Topic")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Viewers")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("TwitchViewCounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.UserDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("Ignored")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("KfId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("KfUsername")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("UserRight")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.UserWhoWasDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ActivityType")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset>("FirstOccurence")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("LatestOccurence")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("UsersWhoWere");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.WagerDbModel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("GamblerId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Game")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("GameMeta")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("IsComplete")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<decimal>("Multiplier")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("Time")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long>("TimeUnixEpochSeconds")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<decimal>("WagerAmount")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<decimal>("WagerEffect")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GamblerId");
|
||||
|
||||
b.ToTable("Wagers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.GamblerDbModel", b =>
|
||||
{
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.UserDbModel", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.GamblerExclusionDbModel", b =>
|
||||
{
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.GamblerDbModel", "Gambler")
|
||||
.WithMany()
|
||||
.HasForeignKey("GamblerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Gambler");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.GamblerPerkDbModel", b =>
|
||||
{
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.GamblerDbModel", "Gambler")
|
||||
.WithMany()
|
||||
.HasForeignKey("GamblerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Gambler");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.ImageDbModel", b =>
|
||||
{
|
||||
b.OwnsOne("KfChatDotNetBot.Models.DbModels.ImageMetadataModel", "Metadata", b1 =>
|
||||
{
|
||||
b1.Property<int>("ImageDbModelId");
|
||||
|
||||
b1.Property<int>("AddedByUserId");
|
||||
|
||||
b1.Property<DateTimeOffset>("WhenAdded");
|
||||
|
||||
b1.HasKey("ImageDbModelId");
|
||||
|
||||
b1.ToTable("Images");
|
||||
|
||||
b1
|
||||
.ToJson("Metadata")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("ImageDbModelId");
|
||||
});
|
||||
|
||||
b.Navigation("Metadata");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.JuicerDbModel", b =>
|
||||
{
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.UserDbModel", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.MomDbModel", b =>
|
||||
{
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.UserDbModel", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.StreamDbModel", b =>
|
||||
{
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.UserDbModel", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.TransactionDbModel", b =>
|
||||
{
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.GamblerDbModel", "From")
|
||||
.WithMany()
|
||||
.HasForeignKey("FromId");
|
||||
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.GamblerDbModel", "Gambler")
|
||||
.WithMany()
|
||||
.HasForeignKey("GamblerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("From");
|
||||
|
||||
b.Navigation("Gambler");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.UserWhoWasDbModel", b =>
|
||||
{
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.UserDbModel", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.WagerDbModel", b =>
|
||||
{
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.GamblerDbModel", "Gambler")
|
||||
.WithMany()
|
||||
.HasForeignKey("GamblerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Gambler");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
28
KfChatDotNetBot/Migrations/20260510194844_ImageMetadata.cs
Normal file
28
KfChatDotNetBot/Migrations/20260510194844_ImageMetadata.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace KfChatDotNetBot.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class ImageMetadata : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Metadata",
|
||||
table: "Images",
|
||||
type: "TEXT",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Metadata",
|
||||
table: "Images");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ namespace KfChatDotNetBot.Migrations
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "9.0.4");
|
||||
modelBuilder.HasAnnotation("ProductVersion", "10.0.3");
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.ChipsggBetDbModel", b =>
|
||||
{
|
||||
@@ -212,6 +212,10 @@ namespace KfChatDotNetBot.Migrations
|
||||
b.Property<DateTimeOffset>("LastSeen")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.PrimitiveCollection<string>("TagList")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Tags")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
@@ -558,6 +562,31 @@ namespace KfChatDotNetBot.Migrations
|
||||
b.Navigation("Gambler");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.ImageDbModel", b =>
|
||||
{
|
||||
b.OwnsOne("KfChatDotNetBot.Models.DbModels.ImageMetadataModel", "Metadata", b1 =>
|
||||
{
|
||||
b1.Property<int>("ImageDbModelId");
|
||||
|
||||
b1.Property<int>("AddedByUserId");
|
||||
|
||||
b1.Property<DateTimeOffset>("WhenAdded");
|
||||
|
||||
b1.HasKey("ImageDbModelId");
|
||||
|
||||
b1.ToTable("Images");
|
||||
|
||||
b1
|
||||
.ToJson("Metadata")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("ImageDbModelId");
|
||||
});
|
||||
|
||||
b.Navigation("Metadata");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("KfChatDotNetBot.Models.DbModels.JuicerDbModel", b =>
|
||||
{
|
||||
b.HasOne("KfChatDotNetBot.Models.DbModels.UserDbModel", "User")
|
||||
|
||||
@@ -6,5 +6,29 @@ public class ImageDbModel
|
||||
public required string Key { get; set; }
|
||||
public required string Url { get; set; }
|
||||
public required DateTimeOffset LastSeen { get; set; }
|
||||
[Obsolete("Use TagList instead")]
|
||||
public string? Tags { get; set; }
|
||||
/// <summary>
|
||||
/// List of image tags for recalling specific images
|
||||
/// </summary>
|
||||
public required List<string> TagList { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// JSON object containing whatever bullshit metadata we want to attach to this image
|
||||
/// Value will be null for images that were added prior to metadata being introduced
|
||||
/// </summary>
|
||||
public required ImageMetadataModel? Metadata { get; set; }
|
||||
}
|
||||
|
||||
public class ImageMetadataModel
|
||||
{
|
||||
/// <summary>
|
||||
/// User ID (IN THE BOT, NOT KIWI FARMS USER ID) of whoever added this image
|
||||
/// </summary>
|
||||
public required int AddedByUserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When the image was added to the database
|
||||
/// </summary>
|
||||
public required DateTimeOffset WhenAdded { get; set; }
|
||||
}
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
using System.Text;
|
||||
using KfChatDotNetBot.Migrations;
|
||||
using KfChatDotNetBot.Services;
|
||||
using KfChatDotNetBot.Settings;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@@ -49,6 +50,21 @@ namespace KfChatDotNetBot
|
||||
logger.Error("Caught an error when attempting to grab the Redis multiplexer");
|
||||
logger.Error(e);
|
||||
}
|
||||
|
||||
if (await db.Images.AnyAsync())
|
||||
{
|
||||
logger.Info("Checking to see if we need to migrate Tags to TagList");
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
var scope = (await db.Images.Where(i => i.Tags != null).ToListAsync()).Where(i => i.TagList.Count == 0).ToList();
|
||||
foreach (var item in scope)
|
||||
{
|
||||
// Ignoring the null as my query literally filters for != null
|
||||
item.TagList = item.Tags!.Split(" ").ToList();
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
logger.Info($"Migrated tags for image {item.Id}");
|
||||
}
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
logger.Info("Handing over to bot now");
|
||||
Console.OutputEncoding = Encoding.UTF8;
|
||||
_ = new ChatBot();
|
||||
|
||||
Reference in New Issue
Block a user