Browse Source

Updated DB Schema and added new initial create

Philipp Häfelfinger 4 months ago
parent
commit
15e2a650b9

+ 1 - 1
Tv7Playlist.Core/IPlaylistBuilder.cs

@@ -5,6 +5,6 @@ namespace Tv7Playlist.Core
 {
     public interface IPlaylistBuilder
     {
-        Task<Stream> GeneratePlaylistAsync();
+        Task<Stream> GeneratePlaylistAsync(bool useProxy);
     }
 }

+ 52 - 15
Tv7Playlist.Core/PlaylistBuilder.cs

@@ -2,6 +2,7 @@ using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using System.Text;
 using System.Threading.Tasks;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.Extensions.Logging;
@@ -20,42 +21,78 @@ namespace Tv7Playlist.Core
             _playlistContext = playlistContext ?? throw new ArgumentNullException(nameof(playlistContext));
         }
 
-        public async Task<Stream> GeneratePlaylistAsync()
+        public async Task<Stream> GeneratePlaylistAsync(bool useProxy)
         {
             _logger.LogInformation(LoggingEvents.Playlist, "Building m3u file content");
 
             var playlistEntries = await _playlistContext.PlaylistEntries.Where(e => e.IsAvailable).Where(e => e.IsEnabled)
                 .OrderBy(e => e.Position).AsNoTracking().ToListAsync();
 
-
-            return await CreatePlaylistStreamAsync(playlistEntries);
+            return await CreatePlaylistStreamAsync(playlistEntries, useProxy);
         }
 
-        private static async Task<MemoryStream> CreatePlaylistStreamAsync(IEnumerable<PlaylistEntry> playlistEntries)
+        private static async Task<MemoryStream> CreatePlaylistStreamAsync(IEnumerable<PlaylistEntry> playlistEntries, bool useProxy)
         {
             var outStream = new MemoryStream();
             var outWriter = new StreamWriter(outStream);
 
             await outWriter.WriteLineAsync(M3UConstants.ExtFileStartTag);
 
-            foreach (var entry in playlistEntries) await WriteEntryAsync(outWriter, entry);
+            foreach (var entry in playlistEntries) await WriteM3UEntryAsync(outWriter, entry, useProxy);
 
-            outStream.Seek(0, SeekOrigin.Begin);
+            await outWriter.FlushAsync();
             
+            outStream.Seek(0, SeekOrigin.Begin);
+
             return outStream;
         }
 
-        private static async Task WriteEntryAsync(TextWriter outWriter, PlaylistEntry entry)
+        private static async Task WriteM3UEntryAsync(TextWriter outWriter, PlaylistEntry entry, bool useProxy)
+        {
+            await WriteExtInfoLineAsync(outWriter, entry);
+            await WriteUrlAsync(outWriter, entry, useProxy);
+        }
+
+        private static async Task WriteUrlAsync(TextWriter outWriter, PlaylistEntry entry, bool useProxy)
+        {
+            if (useProxy)
+                await outWriter.WriteLineAsync(entry.UrlProxy);
+            else
+                await outWriter.WriteLineAsync(entry.UrlOriginal);
+        }
+
+        private static async Task WriteExtInfoLineAsync(TextWriter outWriter, PlaylistEntry entry)
         {
+            // telly default tags from 1.1 dev code:
+            // - NameKey # Parsed from the end of the exif by default
+            // - ChannelNumberKey = "tvg-chno"                          
+            // - LogoKey = "tvg-logo"
+            // - EPGMatchKey = "tvg-id"
+            //#EXTINF:-1 tvg-chno="34" tvg-id="SRF1HD" tvg-logo="http://<url to image file with logo>",test
+            var exInfoBuilder = new StringBuilder();
+            exInfoBuilder.Append(M3UConstants.ExtInfStartTag);
+
             const int duration = -1;
-            var number = entry.TrackNumberOverride != 0 ? entry.TrackNumberOverride : entry.TrackNumber;
-            var name = !string.IsNullOrWhiteSpace(entry.NameOverride) ? entry.NameOverride : entry.Name;
-            
-            //var extInfo = $"{M3UConstants.ExtInfStartTag}{duration},{number},{name}";
-            //TODO: check tagformat and how to serialize them
-            var extInfo = $"{M3UConstants.ExtInfStartTag}{duration},{name}";
-            await outWriter.WriteLineAsync(extInfo);
-            await outWriter.WriteLineAsync(entry.Url);
+            exInfoBuilder.Append(duration);
+
+            AddTag(exInfoBuilder, "tvg-chno", entry.ChannelNumberExport.ToString());
+            AddTag(exInfoBuilder, "tvg-id", entry.EpgMatchName);
+
+            if (!string.IsNullOrWhiteSpace(entry.LogoUrl)) AddTag(exInfoBuilder, "tvg-logo", entry.LogoUrl);
+
+            exInfoBuilder.Append(",");
+            exInfoBuilder.Append(entry.Name);
+
+            await outWriter.WriteLineAsync(exInfoBuilder.ToString());
+        }
+
+        private static void AddTag(StringBuilder builder, string name, string value)
+        {
+            builder.Append(" ");
+            builder.Append(name);
+            builder.Append("=\"");
+            builder.Append(value);
+            builder.Append("\"");
         }
     }
 }

+ 12 - 5
Tv7Playlist.Core/PlaylistSynchronizer.cs

@@ -36,7 +36,7 @@ namespace Tv7Playlist.Core
             _logger.LogDebug(LoggingEvents.Synchronize, "Synchronizing playlist from server...");
 
             var tv7Url = GetTv7SourceUrl();
-            var existingEntries = await _playlistContext.PlaylistEntries.ToDictionaryAsync(e => e.TrackNumber);
+            var existingEntries = await _playlistContext.PlaylistEntries.ToDictionaryAsync(e => e.ChannelNumberImport);
             var tracks = await _playlistLoader.LoadPlaylistFromUrl(tv7Url);
 
             MarkNotAvailableEntries(existingEntries, tracks);
@@ -57,7 +57,13 @@ namespace Tv7Playlist.Core
                     _logger.LogInformation(LoggingEvents.Synchronize, $"Adding playlist entry {track.Id} - {track.Name}");
                     entry = new PlaylistEntry
                     {
-                        Id = Guid.NewGuid(), Position = track.Id, TrackNumber = track.Id, IsEnabled = true
+                        Id = Guid.NewGuid(), 
+                        Position = track.Id,
+                        ChannelNumberImport = track.Id,
+                        ChannelNumberExport = track.Id,
+                        EpgMatchName = track.Name?.Replace(" ",string.Empty),
+                        IsEnabled = false,
+                        Created = DateTime.Now
                     };
                     _playlistContext.PlaylistEntries.Add(entry);
                 }
@@ -69,11 +75,12 @@ namespace Tv7Playlist.Core
                 entry.IsAvailable = true;
                 entry.Name = track.Name;
                 entry.UrlOriginal = track.Url;
-                entry.Url = BuildUrl(entry);
+                entry.UrlProxy = BuildProxiedUrl(entry);
+                entry.Modified = DateTime.Now;
             }
         }
 
-        private string BuildUrl(PlaylistEntry entry)
+        private string BuildProxiedUrl(PlaylistEntry entry)
         {
             return MultiCastRegex.Replace(entry.UrlOriginal, $"{_proxyUrl}/$2/");
         }
@@ -118,7 +125,7 @@ namespace Tv7Playlist.Core
             var unavailableEntries = existingEntries.Where(e => tracks.All(t => t.Id != e.Key)).Select(e => e.Value);
             foreach (var entry in unavailableEntries)
             {
-                _logger.LogInformation(LoggingEvents.Synchronize, $"Channel {entry.TrackNumber} - {entry.Name} is no longer available.");
+                _logger.LogInformation(LoggingEvents.Synchronize, $"Channel {entry.ChannelNumberImport} - {entry.Name} is no longer available.");
                 entry.IsAvailable = false;
             }
         }

+ 18 - 12
Tv7Playlist.Data/Migrations/20190125212615_InitialCreate.Designer.cs

@@ -9,7 +9,7 @@ using Tv7Playlist.Data;
 namespace Tv7Playlist.Data.Migrations
 {
     [DbContext(typeof(PlaylistContext))]
-    [Migration("20190125212615_InitialCreate")]
+    [Migration("20190130214707_InitialCreate")]
     partial class InitialCreate
     {
         protected override void BuildTargetModel(ModelBuilder modelBuilder)
@@ -23,31 +23,37 @@ namespace Tv7Playlist.Data.Migrations
                     b.Property<Guid>("Id")
                         .ValueGeneratedOnAdd();
 
-                    b.Property<bool>("IsAvailable");
+                    b.Property<int>("ChannelNumberExport");
 
-                    b.Property<bool>("IsEnabled");
+                    b.Property<int>("ChannelNumberImport");
 
-                    b.Property<string>("Name");
+                    b.Property<DateTime>("Created");
 
-                    b.Property<string>("NameOverride");
+                    b.Property<string>("EpgMatchName");
 
-                    b.Property<int>("Position");
+                    b.Property<bool>("IsAvailable");
+
+                    b.Property<bool>("IsEnabled");
 
-                    b.Property<int>("TrackNumber");
+                    b.Property<string>("LogoUrl");
 
-                    b.Property<int>("TrackNumberOverride");
+                    b.Property<DateTime>("Modified");
 
-                    b.Property<string>("Url");
+                    b.Property<string>("Name");
+
+                    b.Property<int>("Position");
 
                     b.Property<string>("UrlOriginal");
 
-                    b.HasKey("Id");
+                    b.Property<string>("UrlProxy");
 
-                    b.HasIndex("Name");
+                    b.HasKey("Id");
 
-                    b.HasIndex("TrackNumber")
+                    b.HasIndex("ChannelNumberImport")
                         .IsUnique();
 
+                    b.HasIndex("Name");
+
                     b.ToTable("PlaylistEntries");
                 });
 #pragma warning restore 612, 618

+ 13 - 10
Tv7Playlist.Data/Migrations/20190125212615_InitialCreate.cs

@@ -13,14 +13,17 @@ namespace Tv7Playlist.Data.Migrations
                 {
                     Id = table.Column<Guid>(nullable: false),
                     Position = table.Column<int>(nullable: false),
-                    TrackNumber = table.Column<int>(nullable: false),
-                    TrackNumberOverride = table.Column<int>(nullable: false),
+                    ChannelNumberImport = table.Column<int>(nullable: false),
+                    ChannelNumberExport = table.Column<int>(nullable: false),
                     Name = table.Column<string>(nullable: true),
-                    NameOverride = table.Column<string>(nullable: true),
-                    Url = table.Column<string>(nullable: true),
+                    EpgMatchName = table.Column<string>(nullable: true),
+                    UrlProxy = table.Column<string>(nullable: true),
                     UrlOriginal = table.Column<string>(nullable: true),
+                    LogoUrl = table.Column<string>(nullable: true),
                     IsAvailable = table.Column<bool>(nullable: false),
-                    IsEnabled = table.Column<bool>(nullable: false)
+                    IsEnabled = table.Column<bool>(nullable: false),
+                    Created = table.Column<DateTime>(nullable: false),
+                    Modified = table.Column<DateTime>(nullable: false)
                 },
                 constraints: table =>
                 {
@@ -28,15 +31,15 @@ namespace Tv7Playlist.Data.Migrations
                 });
 
             migrationBuilder.CreateIndex(
-                name: "IX_PlaylistEntries_Name",
+                name: "IX_PlaylistEntries_ChannelNumberImport",
                 table: "PlaylistEntries",
-                column: "Name");
+                column: "ChannelNumberImport",
+                unique: true);
 
             migrationBuilder.CreateIndex(
-                name: "IX_PlaylistEntries_TrackNumber",
+                name: "IX_PlaylistEntries_Name",
                 table: "PlaylistEntries",
-                column: "TrackNumber",
-                unique: true);
+                column: "Name");
         }
 
         protected override void Down(MigrationBuilder migrationBuilder)

+ 17 - 11
Tv7Playlist.Data/Migrations/PlaylistContextModelSnapshot.cs

@@ -21,31 +21,37 @@ namespace Tv7Playlist.Data.Migrations
                     b.Property<Guid>("Id")
                         .ValueGeneratedOnAdd();
 
-                    b.Property<bool>("IsAvailable");
+                    b.Property<int>("ChannelNumberExport");
 
-                    b.Property<bool>("IsEnabled");
+                    b.Property<int>("ChannelNumberImport");
 
-                    b.Property<string>("Name");
+                    b.Property<DateTime>("Created");
 
-                    b.Property<string>("NameOverride");
+                    b.Property<string>("EpgMatchName");
 
-                    b.Property<int>("Position");
+                    b.Property<bool>("IsAvailable");
+
+                    b.Property<bool>("IsEnabled");
 
-                    b.Property<int>("TrackNumber");
+                    b.Property<string>("LogoUrl");
 
-                    b.Property<int>("TrackNumberOverride");
+                    b.Property<DateTime>("Modified");
 
-                    b.Property<string>("Url");
+                    b.Property<string>("Name");
+
+                    b.Property<int>("Position");
 
                     b.Property<string>("UrlOriginal");
 
-                    b.HasKey("Id");
+                    b.Property<string>("UrlProxy");
 
-                    b.HasIndex("Name");
+                    b.HasKey("Id");
 
-                    b.HasIndex("TrackNumber")
+                    b.HasIndex("ChannelNumberImport")
                         .IsUnique();
 
+                    b.HasIndex("Name");
+
                     b.ToTable("PlaylistEntries");
                 });
 #pragma warning restore 612, 618

+ 1 - 1
Tv7Playlist.Data/PlaylistContext.cs

@@ -17,7 +17,7 @@ namespace Tv7Playlist.Data
 
             var entityTypeBuilder = modelBuilder.Entity<PlaylistEntry>();
             entityTypeBuilder.HasKey(e => e.Id);
-            entityTypeBuilder.HasIndex(e => e.TrackNumber).IsUnique();
+            entityTypeBuilder.HasIndex(e => e.ChannelNumberImport).IsUnique();
             entityTypeBuilder.HasIndex(e => e.Name);
         }
     }

+ 11 - 5
Tv7Playlist.Data/PlaylistEntry.cs

@@ -8,20 +8,26 @@ namespace Tv7Playlist.Data
 
         public int Position { get; set; }
 
-        public int TrackNumber { get; set; }
+        public int ChannelNumberImport { get; set; }
 
-        public int TrackNumberOverride { get; set; }
+        public int ChannelNumberExport { get; set; }
 
         public string Name { get; set; }
 
-        public string NameOverride { get; set; }
+        public string EpgMatchName { get; set; }
+
+        public string UrlProxy { get; set; }
 
-        public string Url { get; set; }
-        
         public string UrlOriginal { get; set; }
 
+        public string LogoUrl { get; set; }
+
         public bool IsAvailable { get; set; }
 
         public bool IsEnabled { get; set; }
+
+        public DateTime Created { get; set; }
+
+        public DateTime Modified { get; set; }
     }
 }

+ 1 - 1
Tv7Playlist/Controllers/HomeController.cs

@@ -26,7 +26,7 @@ namespace Tv7Playlist.Controllers
         [HttpGet]
         public async Task<IActionResult> Index()
         {
-            var playlistEntries = await _playlistContext.PlaylistEntries.AsNoTracking().OrderBy(e => e.TrackNumber).ToListAsync();
+            var playlistEntries = await _playlistContext.PlaylistEntries.AsNoTracking().OrderBy(e => e.Position).ToListAsync();
             var model = new HomeModel(playlistEntries);
 
             return View(model);

+ 20 - 1
Tv7Playlist/Controllers/PlaylistApiController.cs

@@ -26,10 +26,29 @@ namespace Tv7Playlist.Controllers
         }
 
         [HttpGet]
+        [Route("without-proxy")]
+        public async Task<IActionResult> GetPlaylistWithoutProxy()
+        {
+            return await GetPlaylistInternal(false);
+        }
+
+        [HttpGet]
         [Route("")]
         public async Task<IActionResult> GetPlaylist()
         {
-            var playlistStream = await _playlistBuilder.GeneratePlaylistAsync();
+            return await GetPlaylistInternal(true);
+        }
+
+        [HttpGet]
+        [Route("with-proxy")]
+        public async Task<IActionResult> GetPlaylistWithProxy()
+        {
+            return await GetPlaylistInternal(true);
+        }
+
+        private async Task<IActionResult> GetPlaylistInternal(bool useProxy)
+        {
+            var playlistStream = await _playlistBuilder.GeneratePlaylistAsync(useProxy);
             var downloadFileName = GetDownloadFileName();
 
             _logger.LogInformation(LoggingEvents.Playlist, "Sending updated playlist {filename}",

+ 4 - 2
Tv7Playlist/Controllers/PlaylistEntryController.cs

@@ -43,9 +43,11 @@ namespace Tv7Playlist.Controllers
                 if (entry == null) return NotFound();
 
                 entry.Position = updatedEntry.Position;
-                entry.TrackNumberOverride = updatedEntry.TrackNumberOverride;
-                entry.NameOverride = updatedEntry.NameOverride;
+                entry.ChannelNumberExport = updatedEntry.ChannelNumberExport;
+                entry.EpgMatchName = updatedEntry.EpgMatchName;
                 entry.IsEnabled = updatedEntry.IsEnabled;
+                entry.LogoUrl = updatedEntry.LogoUrl;
+                entry.Modified = DateTime.Now;
 
                 await _playlistContext.SaveChangesAsync();
 

+ 13 - 9
Tv7Playlist/Views/Home/Index.cshtml

@@ -8,15 +8,17 @@
         <table class="table table-hover table-striped">
             <tr>
                 <th></th>
-                <th>Number</th>
-                <th>Number override</th>
+                <th>Number Import</th>
+                <th>Number Export</th>
                 <th>Position</th>
                 <th>Name</th>
-                <th>Name override</th>
+                <th>EPG Name</th>
                 <th>Enabled</th>
                 <th>Available</th>
-                <th>URL</th>
-                <th>original URL</th>
+                <th>URL Proxy</th>
+                <th>URL Original</th>
+                <th>Created</th>
+                <th>Modified</th>
             </tr>
 
             @{
@@ -24,15 +26,17 @@
                 {
                     <tr>
                         <td><a class="btn btn-secondary" asp-area="" asp-controller="PlaylistEntry" asp-action="Edit" asp-route-id="@track.Id">Edit</a></td>
-                        <td>@track.TrackNumber</td>
-                        <td>@(track.TrackNumberOverride==0?string.Empty:track.TrackNumberOverride.ToString())</td>
+                        <td>@track.ChannelNumberImport</td>
+                        <td>@track.ChannelNumberExport</td>
                         <td>@track.Position</td>
                         <td>@track.Name</td>
-                        <td>@track.NameOverride</td>
+                        <td>@track.EpgMatchName</td>
                         <td>@track.IsEnabled</td>
                         <td>@track.IsAvailable</td>
-                        <td>@track.Url</td>
+                        <td>@track.UrlProxy</td>
                         <td>@track.UrlOriginal</td>
+                        <td>@track.Created.ToString("g")</td>
+                        <td>@track.Modified.ToString("g")</td>
                     </tr>
                 }
             }

+ 20 - 9
Tv7Playlist/Views/PlaylistEntry/Edit.cshtml

@@ -1,17 +1,16 @@
 @model Tv7Playlist.Data.PlaylistEntry;
 @{
-    ViewData["Title"] = $"Edit channel {Model.TrackNumber} - {Model.Name}";
+    ViewData["Title"] = $"Edit channel {Model.ChannelNumberExport} - {Model.Name}";
 }
 
 <div class="row">
     <div class="col col-12">
-        <h3>Edit channel @Model.TrackNumber - @Model.Name</h3>
+        <h3>Edit channel @Model.ChannelNumberExport - @Model.Name</h3>
     </div>
 </div>
 
 <hr/>
 
-
 <form asp-action="Edit" class="">
     <input type="hidden" asp-for="Id"/>
 
@@ -54,25 +53,37 @@
 
     <div class="form-group row">
         <div class="offset-sm-2 col-sm-2">
-            <label asp-for="NameOverride" class="control-label">Name override:</label>
+            <label asp-for="EpgMatchName" class="control-label">EPG Name:</label>
         </div>
         <div class="col-sm-4">
-            <input asp-for="NameOverride" class="form-control"/>
+            <input asp-for="EpgMatchName" class="form-control"/>
         </div>
         <div class="col-sm-2">
-            <span asp-validation-for="NameOverride" class="text-danger"></span>
+            <span asp-validation-for="EpgMatchName" class="text-danger"></span>
         </div>
     </div>
 
     <div class="form-group row">
         <div class="offset-sm-2 col-sm-2">
-            <label asp-for="TrackNumberOverride" class="control-label">Track number override</label>
+            <label asp-for="ChannelNumberExport" class="control-label">Channel number export:</label>
+        </div>
+        <div class="col-sm-4">
+            <input asp-for="ChannelNumberExport" class="form-control"/>
+        </div>
+        <div class="col-sm-2">
+            <span asp-validation-for="ChannelNumberExport" class="text-danger"></span>
+        </div>
+    </div>
+    
+    <div class="form-group row">
+        <div class="offset-sm-2 col-sm-2">
+            <label asp-for="LogoUrl" class="control-label">Logo URL:</label>
         </div>
         <div class="col-sm-4">
-            <input asp-for="TrackNumberOverride" class="form-control"/>
+            <input asp-for="LogoUrl" class="form-control"/>
         </div>
         <div class="col-sm-2">
-            <span asp-validation-for="TrackNumberOverride" class="text-danger"></span>
+            <span asp-validation-for="LogoUrl" class="text-danger"></span>
         </div>
     </div>
 

+ 4 - 1
Tv7Playlist/Views/Shared/_Layout.cshtml

@@ -32,7 +32,10 @@
                         <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Synchronize">Synchronize playlist</a>
                     </li>
                     <li class="nav-item">
-                        <a class="nav-link text-dark" asp-area="" asp-controller="PlaylistApi" asp-action="GetPlaylist">Download playlist / Copy this link to the list</a>
+                        <a class="nav-link text-dark" asp-area="" asp-controller="PlaylistApi" asp-action="GetPlaylistWithProxy">Playlist with Proxy</a>
+                    </li>
+                    <li class="nav-item">
+                        <a class="nav-link text-dark" asp-area="" asp-controller="PlaylistApi" asp-action="GetPlaylistWithoutProxy">Playlist without Proxy</a>
                     </li>
                 </ul>
             </div>