Files
vtuber-awards/Backend/Data/SeedCatalog.cs
T
AzuTear b53c7fb736 Add viewer-range categories, nomination tracking, dynamic showact form, session timeout, share URLs, and workflow-per-season
Features:
- Category viewer ranges + subcategory templates (admin group modal, tree workspace)
- Nomination enrichment via TwitchTracker API (NominationEnrichmentService,
  TwitchTrackerViewerStatsProvider) with admin tracking rules editor
- Nomination group tracker: CategoryGroupName as primary identifier,
  CategoryId stays as nullable legacy field; StreamerIdentity table
- Dynamic showact application form builder (AdminShowactFormBuilder,
  ShowactApplicationSchedule)
- Session idle timeout setting (AdminSessionTimeoutCard)
- Share URLs for X and Discord (SiteSettings, public extras)
- Workflow rules now stored per season (falls back to global SiteSettings)
- New admin routes: settings/access, settings/workflows, tracking-rules
- New admin review workspace with subcategory tabs
- AdminCategoriesView rebuilt with group/subcategory modals

Migrations (all additive):
- AddShareUrls, AddShowactDynamicForm, AddCategoryViewerRanges,
  AddSessionIdleTimeoutSettings, AddSeasonSubcategoryTemplates,
  AddNominationGroupTrackerIdentity, AddShowactApplicationSchedule,
  AddSeasonWorkflowRulesJson

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 23:32:21 +02:00

145 lines
8.5 KiB
C#

namespace Backend.Data;
using Backend.Services;
internal sealed record AwardCategorySeed(string LegacyGroupName, string Name, string Slug, string Description, int SortOrder);
internal sealed record CandidateSeed(string CategorySlug, string DisplayName, string ChannelSlug, string Platform);
internal sealed record WinnerSeed(int Year, string CategorySlug, string DisplayName, string ChannelSlug, string Platform);
internal sealed record SiteFaqSeed(string Question, string Answer);
internal sealed record SiteSocialSeed(string Label, string Platform, string Url, string Icon);
internal static class SeedCatalog
{
internal static readonly SeasonSubcategoryTemplateSetting[] DefaultSubcategoryTemplates =
[
new("Hidden Star", "hidden-star", 1, 1, 20),
new("Rising Star", "rising-star", 2, 21, 60),
new("Shining Star", "shining-star", 3, 61, null),
];
internal static readonly AwardCategorySeed[] AwardCategorySeeds =
[
new("Main Awards", "VTuber des Jahres", "vtuber-des-jahres", "Die größte Auszeichnung des Jahres.", 1),
new("Discovery", "Best Newcomer", "best-newcomer", "Neue Stimmen, neue Welten und frische Energie für die Szene.", 2),
new("Creative", "Model & Design", "model-design", "Live2D, 3D, Outfit, Rigging und visuelle Identitaet.", 3),
new("Performance", "Gesang & Musik", "gesang-musik", "Songs, Covers, Konzerte und musikalische Highlights.", 4),
new("Gaming", "Best Gaming", "best-gaming", "Gameplay, Skill, Chaos und legendaere Gaming-Momente.", 5),
new("Entertainment", "Best Variety", "best-variety", "Talk, Comedy, Watchalongs und kreative Streamformate.", 6),
new("Community", "Community Liebling", "community-liebling", "Creator:innen, die ihre Community besonders stark verbinden.", 7),
new("Collab", "Best Collab & Duo", "best-collab-duo", "Gemeinsame Streams, Projekte und Duo-Dynamik.", 8),
];
internal static readonly Dictionary<string, string> LegacyCategorySlugMap = new(StringComparer.OrdinalIgnoreCase)
{
["bestes-live-event"] = "best-newcomer",
["clip-des-jahres"] = "model-design",
["beste-community"] = "gesang-musik",
};
internal static readonly SiteFaqSeed[] SiteFaqSeeds =
[
new(
"Wer darf nominiert werden?",
"Jede:r aktive deutschsprachige VTuber kann nominiert werden — unabhaengig von Follower-Zahl oder Plattform. Die Community schlaegt in der Nominierungsphase ihre Favorit:innen vor."),
new(
"Wie funktioniert das Voting?",
"Du meldest dich ausschließlich mit deinem Twitch-Account an — nur so kannst du teilnehmen. Das hält das Voting fair und bot-frei. Danach vergibst du pro Kategorie eine Stimme, änderbar bis zum Ende der Phase."),
new(
"Was kostet die Teilnahme?",
"Gar nichts. Nominieren, voten und die Show schauen ist komplett kostenlos — der VTuber Star Award ist ein Community-Event von Fans für Fans."),
new(
"Wann und wo findet die Award-Show statt?",
"Die große Live-Show wird von Jayuhime gehostet und auf Twitch & YouTube gestreamt. Den genauen Termin findest du im Countdown oben — sei live dabei, wenn die Stars gekürt werden!"),
new(
"Ich wurde nominiert — was nun?",
"Glückwunsch! Du erhältst eine Benachrichtigung mit allen Infos. Teile deine Nominierung gern mit deiner Community und ruf zum Voten auf — jede Stimme zählt."),
];
internal static readonly SiteSocialSeed[] SiteSocialSeeds =
[
new("Twitch", "twitch", "https://twitch.tv/jayuhime", "twitch"),
new("YouTube", "youtube", "https://youtube.com/c/Jayuhime", "youtube"),
new("X", "x", "https://x.com/jayuhime", "x"),
new("Instagram", "instagram", "https://instagram.com/jayuhime", "instagram"),
new("Discord", "discord", "https://discord.gg/jayuhime", "discord"),
];
internal const string DefaultImprintContent = """
Anbieter
VTuber Star Awards, vertreten durch Jayuhime.
Kontakt
Nutze für organisatorische Fragen bitte die Kontaktseite oder die hinterlegte Kontaktadresse.
Hinweis
Dieses Impressum ist ein redaktioneller Platzhalter und sollte vor dem Livegang mit den tatsächlichen Anbieterangaben ersetzt werden.
""";
internal const string DefaultContactContent = """
Kontakt zum Award-Team
Du hast Fragen zur Nominierung, zum Voting, zu Clips oder zur Show? Schreib dem Team über die hinterlegte Kontaktseite.
Datenschutzfragen
Für Datenschutzanfragen nutze bitte die Datenschutz-E-Mail aus diesem Footer.
Community & Kooperationen
Social Links und Partneranfragen werden vom Admin-Team gepflegt und koordiniert.
""";
internal const string DefaultSponsorsContent = """
Sponsoren & Partner
Hier können Sponsor:innen, Medienpartner, Community-Partner und Supporter des VTuber Star Awards vorgestellt werden.
Partner werden im Rahmen der Show und auf den öffentlichen Kontaktflächen genannt, sobald sie final bestätigt sind.
""";
internal static readonly CandidateSeed[] CurrentCandidateSeeds =
[
new("vtuber-des-jahres-shining-star", "Hoshimi Miyu", "@hoshimimiyu", "Twitch"),
new("vtuber-des-jahres-shining-star", "Kurainu", "@kurainu", "Twitch"),
new("vtuber-des-jahres-shining-star", "Shiro Ch.", "@shiroch", "Twitch"),
new("best-newcomer-hidden-star", "Aoi Sakura", "@aoisakura", "YouTube"),
new("best-newcomer-rising-star", "Nox Live", "@noxlive", "Twitch"),
new("model-design-shining-star", "Velvet Rei", "@velvetrei", "Twitch"),
new("model-design-rising-star", "Mochi Atelier", "@mochiatelier", "Cake"),
new("gesang-musik-shining-star", "Melo Diva", "@melodiva", "YouTube"),
new("gesang-musik-rising-star", "Yuki Stern", "@yukistern", "Twitch"),
new("best-gaming-shining-star", "Kurainu", "@kurainu", "Twitch"),
new("best-gaming-rising-star", "PixelPunk", "@pixelpunk", "Twitch"),
new("best-variety-shining-star", "Taro Chaos", "@tarochaos", "Twitch"),
new("best-variety-rising-star", "Kotaro Plays", "@kotaroplays", "YouTube"),
new("community-liebling-shining-star", "Shiro Ch.", "@shiroch", "Twitch"),
new("community-liebling-hidden-star", "Lumi", "@lumi_vt", "Cake"),
new("best-collab-duo-shining-star", "Akari & Nox", "@akari_vt", "Twitch"),
new("best-collab-duo-rising-star", "Mochi & Hana", "@mochi_mochi", "YouTube"),
];
internal static readonly WinnerSeed[] WinnerSeeds =
[
new(2025, "vtuber-des-jahres-shining-star", "Hoshimi Miyu", "@hoshimimiyu", "Twitch"),
new(2025, "best-newcomer-hidden-star", "Aoi Sakura", "@aoisakura", "YouTube"),
new(2025, "model-design-shining-star", "Velvet Rei", "@velvetrei", "Twitch"),
new(2025, "gesang-musik-shining-star", "Melo Diva", "@melodiva", "YouTube"),
new(2025, "best-gaming-shining-star", "Kurainu", "@kurainu", "Twitch"),
new(2025, "best-variety-shining-star", "Taro Chaos", "@tarochaos", "Twitch"),
new(2025, "community-liebling-shining-star", "Shiro Ch.", "@shiroch", "Twitch"),
new(2025, "best-collab-duo-shining-star", "Akari & Nox", "@akari_vt", "Cake"),
new(2024, "vtuber-des-jahres-shining-star", "Aoi Sakura", "@aoisakura", "YouTube"),
new(2024, "best-newcomer-hidden-star", "Lumi", "@lumi_vt", "Cake"),
new(2024, "model-design-rising-star", "Mochi Atelier", "@mochiatelier", "Cake"),
new(2024, "gesang-musik-rising-star", "Yuki Stern", "@yukistern", "Twitch"),
new(2024, "best-gaming-shining-star", "Starbyte", "@starbyte", "Twitch"),
new(2024, "best-variety-rising-star", "Kotaro Plays", "@kotaroplays", "YouTube"),
new(2024, "community-liebling-rising-star", "Moonrelay", "@moonrelay", "Twitch"),
new(2024, "best-collab-duo-rising-star", "Pixel & Kotaro", "@pixelpunk", "Twitch"),
new(2023, "vtuber-des-jahres-shining-star", "Akari Nova", "@akarinova", "Twitch"),
new(2023, "best-newcomer-rising-star", "Nox Live", "@noxlive", "Twitch"),
new(2023, "model-design-shining-star", "Rei Velvet", "@reivelvet", "YouTube"),
new(2023, "gesang-musik-shining-star", "Tenshi Vox", "@tenshivox", "Twitch"),
new(2023, "best-gaming-rising-star", "Bit Knight", "@bitknight", "Twitch"),
new(2023, "best-variety-hidden-star", "Hana Hearts", "@hanahearts", "Cake"),
new(2023, "community-liebling-rising-star", "Sora Blau", "@sorablau", "YouTube"),
new(2023, "best-collab-duo-rising-star", "Yuki & Melo", "@yukistern", "Twitch"),
];
}