From ce2024306a219644aaece06767a5d888aa9451ad Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 15 May 2026 12:26:34 +0000
Subject: [PATCH] Add IncludeSpecials toggle for station maps and Telegram bot
settings
Agent-Logs-Url: https://github.com/jjasloot/OVDB/sessions/d59c16da-f087-485a-98b1-5b039ffe8e65
Co-authored-by: jjasloot <5612709+jjasloot@users.noreply.github.com>
---
...60515122447_AddIncludeSpecials.Designer.cs | 1346 +++++++++++++++++
.../20260515122447_AddIncludeSpecials.cs | 40 +
.../OVDBDatabaseContextModelSnapshot.cs | 6 +
OVDB_database/Models/StationGrouping.cs | 1 +
OVDB_database/Models/User.cs | 1 +
OV_DB/Controllers/StationMapsController.cs | 10 +-
OV_DB/Mappings/MappingExtensions.cs | 1 +
OV_DB/Models/StationMapDTO.cs | 1 +
.../station-maps-edit.component.html | 5 +
.../station-maps-edit.component.ts | 2 +
.../src/app/models/stationMap.model.ts | 1 +
OV_DB/OVDBFrontend/src/assets/i18n/en.json | 1 +
OV_DB/OVDBFrontend/src/assets/i18n/nl.json | 1 +
OV_DB/Services/TelegramBotService.cs | 94 +-
14 files changed, 1500 insertions(+), 10 deletions(-)
create mode 100644 OVDB_database/Migrations/20260515122447_AddIncludeSpecials.Designer.cs
create mode 100644 OVDB_database/Migrations/20260515122447_AddIncludeSpecials.cs
diff --git a/OVDB_database/Migrations/20260515122447_AddIncludeSpecials.Designer.cs b/OVDB_database/Migrations/20260515122447_AddIncludeSpecials.Designer.cs
new file mode 100644
index 00000000..bd5a4dd3
--- /dev/null
+++ b/OVDB_database/Migrations/20260515122447_AddIncludeSpecials.Designer.cs
@@ -0,0 +1,1346 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using NetTopologySuite.Geometries;
+using OVDB_database.Database;
+
+#nullable disable
+
+namespace OVDB_database.Migrations
+{
+ [DbContext(typeof(OVDBDatabaseContext))]
+ [Migration("20260515122447_AddIncludeSpecials")]
+ partial class AddIncludeSpecials
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "9.0.12")
+ .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+ MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
+
+ modelBuilder.Entity("OVDB_database.Models.InviteCode", b =>
+ {
+ b.Property("InviteCodeId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("InviteCodeId"));
+
+ b.Property("Code")
+ .IsRequired()
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)");
+
+ b.Property("CreatedByUserId")
+ .HasColumnType("int");
+
+ b.Property("DoesNotExpire")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("IsUsed")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("InviteCodeId");
+
+ b.HasIndex("Code")
+ .IsUnique();
+
+ b.HasIndex("CreatedByUserId");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("InviteCodes");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.Map", b =>
+ {
+ b.Property("MapId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("MapId"));
+
+ b.Property("Completed")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Default")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("MapGuid")
+ .HasColumnType("char(36)");
+
+ b.Property("Name")
+ .HasColumnType("longtext");
+
+ b.Property("NameNL")
+ .HasColumnType("longtext");
+
+ b.Property("OrderNr")
+ .HasColumnType("int");
+
+ b.Property("SharingLinkName")
+ .HasColumnType("longtext");
+
+ b.Property("ShowRouteInfo")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("ShowRouteOutline")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("MapId");
+
+ b.HasIndex("MapGuid")
+ .IsUnique();
+
+ b.HasIndex("UserId");
+
+ b.ToTable("Maps");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.Operator", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("LogoContentType")
+ .HasColumnType("longtext");
+
+ b.Property("LogoFilePath")
+ .HasColumnType("longtext");
+
+ b.Property("Names")
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("Operators");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.RefreshToken", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("DeviceInfo")
+ .HasMaxLength(500)
+ .HasColumnType("varchar(500)");
+
+ b.Property("ExpiresAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("IsRevoked")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LastUsedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("RevokedAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Token")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ExpiresAt");
+
+ b.HasIndex("IsRevoked");
+
+ b.HasIndex("Token")
+ .IsUnique();
+
+ b.HasIndex("UserId");
+
+ b.ToTable("RefreshTokens");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.Region", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("FlagEmoji")
+ .HasColumnType("longtext");
+
+ b.Property("Geometry")
+ .HasColumnType("multipolygon");
+
+ b.Property("IsoCode")
+ .HasColumnType("longtext");
+
+ b.Property("Name")
+ .HasColumnType("longtext");
+
+ b.Property("NameNL")
+ .HasColumnType("longtext");
+
+ b.Property("OriginalName")
+ .HasColumnType("longtext");
+
+ b.Property("OsmRelationId")
+ .HasColumnType("bigint");
+
+ b.Property("ParentRegionId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ParentRegionId");
+
+ b.ToTable("Regions");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.Request", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("Created")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Message")
+ .HasColumnType("longtext");
+
+ b.Property("Read")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Responded")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Response")
+ .HasColumnType("longtext");
+
+ b.Property("ResponseRead")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("Requests");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.Route", b =>
+ {
+ b.Property("RouteId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("RouteId"));
+
+ b.Property("CalculatedDistance")
+ .HasColumnType("double");
+
+ b.Property("Description")
+ .HasColumnType("longtext");
+
+ b.Property("DescriptionNL")
+ .HasColumnType("longtext");
+
+ b.Property("FirstDateTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("From")
+ .HasColumnType("longtext");
+
+ b.Property("LineNumber")
+ .HasColumnType("longtext");
+
+ b.Property("LineString")
+ .HasColumnType("linestring");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("varchar(255)");
+
+ b.Property("NameNL")
+ .HasColumnType("longtext");
+
+ b.Property("OperatingCompany")
+ .HasColumnType("longtext");
+
+ b.Property("OverrideColour")
+ .HasColumnType("longtext");
+
+ b.Property("OverrideDistance")
+ .HasColumnType("double");
+
+ b.Property("RouteTypeId")
+ .HasColumnType("int");
+
+ b.Property("Share")
+ .HasColumnType("char(36)");
+
+ b.Property("To")
+ .HasColumnType("longtext");
+
+ b.Property("TrainlogType")
+ .HasColumnType("longtext");
+
+ b.HasKey("RouteId");
+
+ b.HasIndex("Name");
+
+ b.HasIndex("RouteTypeId");
+
+ b.HasIndex("Share");
+
+ b.ToTable("Routes");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.RouteInstance", b =>
+ {
+ b.Property("RouteInstanceId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("RouteInstanceId"));
+
+ b.Property("Date")
+ .HasColumnType("datetime(6)");
+
+ b.Property("DurationHours")
+ .HasColumnType("double");
+
+ b.Property("EndTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("RouteId")
+ .HasColumnType("int");
+
+ b.Property("ScheduledEndTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("ScheduledStartTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("StartTime")
+ .HasColumnType("datetime(6)");
+
+ b.Property("TrawellingStatusId")
+ .HasColumnType("int");
+
+ b.HasKey("RouteInstanceId");
+
+ b.HasIndex("Date");
+
+ b.HasIndex("TrawellingStatusId");
+
+ b.HasIndex(new[] { "Date", "RouteId" }, "idx_routeinstances_date_routeid");
+
+ b.HasIndex(new[] { "RouteId", "Date" }, "idx_routeinstances_routeid_date");
+
+ b.ToTable("RouteInstances");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.RouteInstanceMap", b =>
+ {
+ b.Property("RouteMapId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("RouteMapId"));
+
+ b.Property("MapId")
+ .HasColumnType("int");
+
+ b.Property("RouteInstanceId")
+ .HasColumnType("int");
+
+ b.HasKey("RouteMapId");
+
+ b.HasIndex("MapId");
+
+ b.HasIndex(new[] { "RouteInstanceId", "MapId" }, "idx_routeinstancemap_routeinstanceid_mapid");
+
+ b.ToTable("RouteInstanceMap");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.RouteInstanceProperty", b =>
+ {
+ b.Property("RouteInstancePropertyId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("RouteInstancePropertyId"));
+
+ b.Property("Bool")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Key")
+ .IsRequired()
+ .HasMaxLength(100)
+ .HasColumnType("varchar(100)");
+
+ b.Property("RouteInstanceId")
+ .HasColumnType("int");
+
+ b.Property("Value")
+ .HasColumnType("longtext");
+
+ b.HasKey("RouteInstancePropertyId");
+
+ b.HasIndex("RouteInstanceId", "Key");
+
+ b.ToTable("RouteInstanceProperties");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.RouteMap", b =>
+ {
+ b.Property("RouteMapId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("RouteMapId"));
+
+ b.Property("MapId")
+ .HasColumnType("int");
+
+ b.Property("RouteId")
+ .HasColumnType("int");
+
+ b.HasKey("RouteMapId");
+
+ b.HasIndex("MapId");
+
+ b.HasIndex("RouteId");
+
+ b.ToTable("RoutesMaps");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.RouteType", b =>
+ {
+ b.Property("TypeId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("TypeId"));
+
+ b.Property("Colour")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("IsTrain")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("NameNL")
+ .HasColumnType("longtext");
+
+ b.Property("OrderNr")
+ .HasColumnType("int");
+
+ b.Property("TrainlogType")
+ .HasColumnType("longtext");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("TypeId");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("RouteTypes");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.Station", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("Elevation")
+ .HasColumnType("double");
+
+ b.Property("Hidden")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("tinyint(1)")
+ .HasDefaultValue(false);
+
+ b.Property("Lattitude")
+ .HasColumnType("double");
+
+ b.Property("Longitude")
+ .HasColumnType("double");
+
+ b.Property("Name")
+ .HasColumnType("longtext");
+
+ b.Property("Network")
+ .HasColumnType("longtext");
+
+ b.Property("Operator")
+ .HasColumnType("longtext");
+
+ b.Property("OsmId")
+ .HasColumnType("bigint");
+
+ b.Property("Special")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("tinyint(1)")
+ .HasDefaultValue(false);
+
+ b.Property("StationCountryId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("OsmId");
+
+ b.HasIndex("StationCountryId");
+
+ b.ToTable("Stations");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.StationCountry", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("Name")
+ .HasColumnType("longtext");
+
+ b.Property("NameNL")
+ .HasColumnType("longtext");
+
+ b.Property("OsmId")
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.ToTable("StationCountries");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.StationGrouping", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("IncludeSpecials")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("MapGuid")
+ .HasColumnType("char(36)");
+
+ b.Property("Name")
+ .HasColumnType("longtext");
+
+ b.Property("NameNL")
+ .HasColumnType("longtext");
+
+ b.Property("OrderNr")
+ .HasColumnType("int");
+
+ b.Property("SharingLinkName")
+ .HasColumnType("longtext");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("MapGuid")
+ .IsUnique();
+
+ b.HasIndex("UserId");
+
+ b.ToTable("StationGroupings");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.StationMap", b =>
+ {
+ b.Property("StationMapId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("StationMapId"));
+
+ b.Property("MapGuid")
+ .HasColumnType("char(36)");
+
+ b.Property("Name")
+ .HasColumnType("longtext");
+
+ b.Property("NameNL")
+ .HasColumnType("longtext");
+
+ b.Property("OrderNr")
+ .HasColumnType("int");
+
+ b.Property("SharingLinkName")
+ .HasColumnType("longtext");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("StationMapId");
+
+ b.HasIndex("MapGuid")
+ .IsUnique();
+
+ b.HasIndex("UserId");
+
+ b.ToTable("StationMaps");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.StationMapCountry", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("IncludeSpecials")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("StationCountryId")
+ .HasColumnType("int");
+
+ b.Property("StationMapId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("StationCountryId");
+
+ b.HasIndex("StationMapId");
+
+ b.ToTable("StationMapCountries");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.StationMergeIgnore", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("Station1Id")
+ .HasColumnType("int");
+
+ b.Property("Station2Id")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Station2Id");
+
+ b.HasIndex("Station1Id", "Station2Id")
+ .IsUnique();
+
+ b.ToTable("StationMergeIgnores");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.StationVisit", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("StationId")
+ .HasColumnType("int");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("StationId", "UserId")
+ .IsUnique();
+
+ b.ToTable("StationVisits");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.TrawellingIgnoredStatus", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("IgnoredAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("TrawellingStatusId")
+ .HasColumnType("int");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId", "TrawellingStatusId")
+ .IsUnique();
+
+ b.ToTable("TrawellingIgnoredStatuses");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.TrawellingStation", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int")
+ .HasColumnName("id");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("CreatedAt")
+ .HasColumnType("datetime(6)")
+ .HasColumnName("created_at");
+
+ b.Property("Ibnr")
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)")
+ .HasColumnName("ibnr");
+
+ b.Property("Latitude")
+ .HasColumnType("double")
+ .HasColumnName("latitude");
+
+ b.Property("Longitude")
+ .HasColumnType("double")
+ .HasColumnName("longitude");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("varchar(255)")
+ .HasColumnName("name");
+
+ b.Property("RilIdentifier")
+ .HasMaxLength(50)
+ .HasColumnType("varchar(50)")
+ .HasColumnName("ril_identifier");
+
+ b.Property("TrawellingId")
+ .HasColumnType("int")
+ .HasColumnName("traewelling_id");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("datetime(6)")
+ .HasColumnName("updated_at");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TrawellingId")
+ .IsUnique();
+
+ b.ToTable("trawelling_stations");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.User", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+
+ b.Property("Email")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("varchar(256)");
+
+ b.Property("EnableTrainlogExport")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("Guid")
+ .HasColumnType("char(36)");
+
+ b.Property("IsAdmin")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LastLogin")
+ .HasColumnType("datetime(6)");
+
+ b.Property("Password")
+ .IsRequired()
+ .HasMaxLength(512)
+ .HasColumnType("varchar(512)");
+
+ b.Property("PreferredLanguage")
+ .HasColumnType("int");
+
+ b.Property("RefreshToken")
+ .HasColumnType("longtext");
+
+ b.Property("TelegramIncludeSpecials")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("TelegramUserId")
+ .HasColumnType("bigint");
+
+ b.Property("TraewellingTagMappings")
+ .HasColumnType("longtext");
+
+ b.Property("TrainlogMaterialKey")
+ .HasMaxLength(100)
+ .HasColumnType("varchar(100)");
+
+ b.Property("TrainlogOperatorMappings")
+ .HasColumnType("longtext");
+
+ b.Property("TrainlogRegistrationKey")
+ .HasMaxLength(100)
+ .HasColumnType("varchar(100)");
+
+ b.Property("TrainlogSeatKey")
+ .HasMaxLength(100)
+ .HasColumnType("varchar(100)");
+
+ b.Property("TrawellingAccessToken")
+ .HasColumnType("longtext");
+
+ b.Property("TrawellingRefreshToken")
+ .HasColumnType("longtext");
+
+ b.Property("TrawellingTokenExpiresAt")
+ .HasColumnType("datetime(6)");
+
+ b.Property("TrawellingUsername")
+ .HasColumnType("longtext");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Email")
+ .IsUnique();
+
+ b.HasIndex("Guid")
+ .IsUnique();
+
+ b.HasIndex("TelegramUserId")
+ .IsUnique()
+ .HasFilter("[TelegramUserId] IS NOT NULL");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("OperatorRegion", b =>
+ {
+ b.Property("OperatorsRunningTrainsId")
+ .HasColumnType("int");
+
+ b.Property("RunsTrainsInRegionsId")
+ .HasColumnType("int");
+
+ b.HasKey("OperatorsRunningTrainsId", "RunsTrainsInRegionsId");
+
+ b.HasIndex("RunsTrainsInRegionsId");
+
+ b.ToTable("OperatorRegion");
+ });
+
+ modelBuilder.Entity("OperatorRegion1", b =>
+ {
+ b.Property("OperatorsRestrictedToRegionId")
+ .HasColumnType("int");
+
+ b.Property("RestrictToRegionsId")
+ .HasColumnType("int");
+
+ b.HasKey("OperatorsRestrictedToRegionId", "RestrictToRegionsId");
+
+ b.HasIndex("RestrictToRegionsId");
+
+ b.ToTable("OperatorRegion1");
+ });
+
+ modelBuilder.Entity("OperatorRoute", b =>
+ {
+ b.Property("OperatorsId")
+ .HasColumnType("int");
+
+ b.Property("RoutesRouteId")
+ .HasColumnType("int");
+
+ b.HasKey("OperatorsId", "RoutesRouteId");
+
+ b.HasIndex("RoutesRouteId");
+
+ b.ToTable("OperatorRoute");
+ });
+
+ modelBuilder.Entity("RegionRoute", b =>
+ {
+ b.Property("RegionsId")
+ .HasColumnType("int");
+
+ b.Property("RoutesRouteId")
+ .HasColumnType("int");
+
+ b.HasKey("RegionsId", "RoutesRouteId");
+
+ b.HasIndex("RoutesRouteId");
+
+ b.ToTable("RegionRoute");
+ });
+
+ modelBuilder.Entity("RegionStation", b =>
+ {
+ b.Property("RegionsId")
+ .HasColumnType("int");
+
+ b.Property("StationsId")
+ .HasColumnType("int");
+
+ b.HasKey("RegionsId", "StationsId");
+
+ b.HasIndex("StationsId");
+
+ b.ToTable("RegionStation");
+ });
+
+ modelBuilder.Entity("RegionStationGrouping", b =>
+ {
+ b.Property("RegionsId")
+ .HasColumnType("int");
+
+ b.Property("StationGroupingsId")
+ .HasColumnType("int");
+
+ b.HasKey("RegionsId", "StationGroupingsId");
+
+ b.HasIndex("StationGroupingsId");
+
+ b.ToTable("RegionStationGrouping");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.InviteCode", b =>
+ {
+ b.HasOne("OVDB_database.Models.User", "CreatedByUser")
+ .WithMany()
+ .HasForeignKey("CreatedByUserId")
+ .OnDelete(DeleteBehavior.SetNull);
+
+ b.HasOne("OVDB_database.Models.User", "User")
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.SetNull);
+
+ b.Navigation("CreatedByUser");
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.Map", b =>
+ {
+ b.HasOne("OVDB_database.Models.User", "User")
+ .WithMany("Maps")
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.RefreshToken", b =>
+ {
+ b.HasOne("OVDB_database.Models.User", "User")
+ .WithMany("RefreshTokens")
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.Region", b =>
+ {
+ b.HasOne("OVDB_database.Models.Region", "ParentRegion")
+ .WithMany("SubRegions")
+ .HasForeignKey("ParentRegionId");
+
+ b.Navigation("ParentRegion");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.Request", b =>
+ {
+ b.HasOne("OVDB_database.Models.User", "User")
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.Route", b =>
+ {
+ b.HasOne("OVDB_database.Models.RouteType", "RouteType")
+ .WithMany("Routes")
+ .HasForeignKey("RouteTypeId");
+
+ b.Navigation("RouteType");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.RouteInstance", b =>
+ {
+ b.HasOne("OVDB_database.Models.Route", "Route")
+ .WithMany("RouteInstances")
+ .HasForeignKey("RouteId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Route");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.RouteInstanceMap", b =>
+ {
+ b.HasOne("OVDB_database.Models.Map", "Map")
+ .WithMany()
+ .HasForeignKey("MapId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("OVDB_database.Models.RouteInstance", "RouteInstance")
+ .WithMany("RouteInstanceMaps")
+ .HasForeignKey("RouteInstanceId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Map");
+
+ b.Navigation("RouteInstance");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.RouteInstanceProperty", b =>
+ {
+ b.HasOne("OVDB_database.Models.RouteInstance", "RouteInstance")
+ .WithMany("RouteInstanceProperties")
+ .HasForeignKey("RouteInstanceId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("RouteInstance");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.RouteMap", b =>
+ {
+ b.HasOne("OVDB_database.Models.Map", "Map")
+ .WithMany("RouteMaps")
+ .HasForeignKey("MapId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("OVDB_database.Models.Route", "Route")
+ .WithMany("RouteMaps")
+ .HasForeignKey("RouteId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Map");
+
+ b.Navigation("Route");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.RouteType", b =>
+ {
+ b.HasOne("OVDB_database.Models.User", null)
+ .WithMany("RouteTypes")
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.Station", b =>
+ {
+ b.HasOne("OVDB_database.Models.StationCountry", "StationCountry")
+ .WithMany("Stations")
+ .HasForeignKey("StationCountryId");
+
+ b.Navigation("StationCountry");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.StationGrouping", b =>
+ {
+ b.HasOne("OVDB_database.Models.User", "User")
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.StationMap", b =>
+ {
+ b.HasOne("OVDB_database.Models.User", "User")
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.StationMapCountry", b =>
+ {
+ b.HasOne("OVDB_database.Models.StationCountry", "StationCountry")
+ .WithMany("StationMapCountries")
+ .HasForeignKey("StationCountryId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("OVDB_database.Models.StationMap", "StationMap")
+ .WithMany("StationMapCountries")
+ .HasForeignKey("StationMapId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("StationCountry");
+
+ b.Navigation("StationMap");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.StationMergeIgnore", b =>
+ {
+ b.HasOne("OVDB_database.Models.Station", "Station1")
+ .WithMany()
+ .HasForeignKey("Station1Id")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("OVDB_database.Models.Station", "Station2")
+ .WithMany()
+ .HasForeignKey("Station2Id")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Station1");
+
+ b.Navigation("Station2");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.StationVisit", b =>
+ {
+ b.HasOne("OVDB_database.Models.Station", "Station")
+ .WithMany("StationVisits")
+ .HasForeignKey("StationId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("OVDB_database.Models.User", "User")
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Station");
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.TrawellingIgnoredStatus", b =>
+ {
+ b.HasOne("OVDB_database.Models.User", "User")
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("OperatorRegion", b =>
+ {
+ b.HasOne("OVDB_database.Models.Operator", null)
+ .WithMany()
+ .HasForeignKey("OperatorsRunningTrainsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("OVDB_database.Models.Region", null)
+ .WithMany()
+ .HasForeignKey("RunsTrainsInRegionsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("OperatorRegion1", b =>
+ {
+ b.HasOne("OVDB_database.Models.Operator", null)
+ .WithMany()
+ .HasForeignKey("OperatorsRestrictedToRegionId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("OVDB_database.Models.Region", null)
+ .WithMany()
+ .HasForeignKey("RestrictToRegionsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("OperatorRoute", b =>
+ {
+ b.HasOne("OVDB_database.Models.Operator", null)
+ .WithMany()
+ .HasForeignKey("OperatorsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("OVDB_database.Models.Route", null)
+ .WithMany()
+ .HasForeignKey("RoutesRouteId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("RegionRoute", b =>
+ {
+ b.HasOne("OVDB_database.Models.Region", null)
+ .WithMany()
+ .HasForeignKey("RegionsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("OVDB_database.Models.Route", null)
+ .WithMany()
+ .HasForeignKey("RoutesRouteId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("RegionStation", b =>
+ {
+ b.HasOne("OVDB_database.Models.Region", null)
+ .WithMany()
+ .HasForeignKey("RegionsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("OVDB_database.Models.Station", null)
+ .WithMany()
+ .HasForeignKey("StationsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("RegionStationGrouping", b =>
+ {
+ b.HasOne("OVDB_database.Models.Region", null)
+ .WithMany()
+ .HasForeignKey("RegionsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("OVDB_database.Models.StationGrouping", null)
+ .WithMany()
+ .HasForeignKey("StationGroupingsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.Map", b =>
+ {
+ b.Navigation("RouteMaps");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.Region", b =>
+ {
+ b.Navigation("SubRegions");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.Route", b =>
+ {
+ b.Navigation("RouteInstances");
+
+ b.Navigation("RouteMaps");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.RouteInstance", b =>
+ {
+ b.Navigation("RouteInstanceMaps");
+
+ b.Navigation("RouteInstanceProperties");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.RouteType", b =>
+ {
+ b.Navigation("Routes");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.Station", b =>
+ {
+ b.Navigation("StationVisits");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.StationCountry", b =>
+ {
+ b.Navigation("StationMapCountries");
+
+ b.Navigation("Stations");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.StationMap", b =>
+ {
+ b.Navigation("StationMapCountries");
+ });
+
+ modelBuilder.Entity("OVDB_database.Models.User", b =>
+ {
+ b.Navigation("Maps");
+
+ b.Navigation("RefreshTokens");
+
+ b.Navigation("RouteTypes");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/OVDB_database/Migrations/20260515122447_AddIncludeSpecials.cs b/OVDB_database/Migrations/20260515122447_AddIncludeSpecials.cs
new file mode 100644
index 00000000..2af62033
--- /dev/null
+++ b/OVDB_database/Migrations/20260515122447_AddIncludeSpecials.cs
@@ -0,0 +1,40 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace OVDB_database.Migrations
+{
+ ///
+ public partial class AddIncludeSpecials : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn(
+ name: "TelegramIncludeSpecials",
+ table: "Users",
+ type: "tinyint(1)",
+ nullable: false,
+ defaultValue: false);
+
+ migrationBuilder.AddColumn(
+ name: "IncludeSpecials",
+ table: "StationGroupings",
+ type: "tinyint(1)",
+ nullable: false,
+ defaultValue: false);
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "TelegramIncludeSpecials",
+ table: "Users");
+
+ migrationBuilder.DropColumn(
+ name: "IncludeSpecials",
+ table: "StationGroupings");
+ }
+ }
+}
diff --git a/OVDB_database/Migrations/OVDBDatabaseContextModelSnapshot.cs b/OVDB_database/Migrations/OVDBDatabaseContextModelSnapshot.cs
index dc788632..5e878604 100644
--- a/OVDB_database/Migrations/OVDBDatabaseContextModelSnapshot.cs
+++ b/OVDB_database/Migrations/OVDBDatabaseContextModelSnapshot.cs
@@ -561,6 +561,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id"));
+ b.Property("IncludeSpecials")
+ .HasColumnType("tinyint(1)");
+
b.Property("MapGuid")
.HasColumnType("char(36)");
@@ -813,6 +816,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.Property("RefreshToken")
.HasColumnType("longtext");
+ b.Property("TelegramIncludeSpecials")
+ .HasColumnType("tinyint(1)");
+
b.Property("TelegramUserId")
.HasColumnType("bigint");
diff --git a/OVDB_database/Models/StationGrouping.cs b/OVDB_database/Models/StationGrouping.cs
index 59307ae0..af11ca7f 100644
--- a/OVDB_database/Models/StationGrouping.cs
+++ b/OVDB_database/Models/StationGrouping.cs
@@ -21,6 +21,7 @@ public class StationGrouping
[JsonProperty]
public string? SharingLinkName { get; set; }
public int OrderNr { get; set; }
+ public bool IncludeSpecials { get; set; }
public User? User { get; set; }
public List Regions { get; set; }
}
diff --git a/OVDB_database/Models/User.cs b/OVDB_database/Models/User.cs
index f519f219..06e41d2d 100644
--- a/OVDB_database/Models/User.cs
+++ b/OVDB_database/Models/User.cs
@@ -33,6 +33,7 @@ public class User
public List