Skip to content

Commit

Permalink
EPG M3U Cleanup (#123)
Browse files Browse the repository at this point in the history
* Feature Request: Choose between MPEG-TS(.ts)/HLS(.m3u8) if provider supports it
Fixes #77

and some cleanup ;)

* Feature Request: Choose between MPEG-TS(.ts)/HLS(.m3u8) if provider supports it
Fixes #77

* EPG M3U Cleanup

* removed signalr debug
  • Loading branch information
SenexCrenshaw authored Oct 14, 2023
1 parent d387ebe commit 010e070
Show file tree
Hide file tree
Showing 163 changed files with 3,458 additions and 4,322 deletions.
25 changes: 3 additions & 22 deletions StreamMasterApplication/M3UFiles/Commands/CreateM3UFileRequest.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,14 @@
using FluentValidation;

using Microsoft.AspNetCore.Http;

using StreamMasterDomain.Models;
using Microsoft.AspNetCore.Http;

using System.Web;

namespace StreamMasterApplication.M3UFiles.Commands;

public record CreateM3UFileRequest(string? Description, int MaxStreamCount, int? StartingChannelNumber, IFormFile? FormFile, string Name, string? UrlSource) : IRequest<bool> { }

public class CreateM3UFileRequestValidator : AbstractValidator<CreateM3UFileRequest>
{
public CreateM3UFileRequestValidator()
{
_ = RuleFor(v => v.Name)
.MaximumLength(32)
.NotEmpty();

_ = RuleFor(v => v.UrlSource).NotEmpty().When(v => v.FormFile == null);
_ = RuleFor(v => v.FormFile).NotNull().When(v => string.IsNullOrEmpty(v.UrlSource));
}
}

[LogExecutionTimeAspect]
public class CreateM3UFileRequestHandler : BaseMediatorRequestHandler, IRequestHandler<CreateM3UFileRequest, bool>
public class CreateM3UFileRequestHandler(ILogger<CreateM3UFileRequest> logger, IRepositoryWrapper repository, IMapper mapper, ISettingsService settingsService, IPublisher publisher, ISender sender, IHubContext<StreamMasterHub, IStreamMasterHub> hubContext, IMemoryCache memoryCache) : BaseMediatorRequestHandler(logger, repository, mapper, settingsService, publisher, sender, hubContext, memoryCache), IRequestHandler<CreateM3UFileRequest, bool>
{
public CreateM3UFileRequestHandler(ILogger<CreateM3UFileRequest> logger, IRepositoryWrapper repository, IMapper mapper, ISettingsService settingsService, IPublisher publisher, ISender sender, IHubContext<StreamMasterHub, IStreamMasterHub> hubContext, IMemoryCache memoryCache)
: base(logger, repository, mapper, settingsService, publisher, sender, hubContext, memoryCache) { }

public async Task<bool> Handle(CreateM3UFileRequest command, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(command.UrlSource) && command.FormFile != null && command.FormFile.Length <= 0)
Expand All @@ -48,6 +28,7 @@ public async Task<bool> Handle(CreateM3UFileRequest command, CancellationToken c
Name = command.Name,
Source = command.Name + fd.FileExtension,
StartingChannelNumber = command.StartingChannelNumber == null ? 1 : (int)command.StartingChannelNumber,
//StreamURLPrefix = command.StreamURLPrefixInt == null ? M3UFileStreamURLPrefix.SystemDefault : (M3UFileStreamURLPrefix)command.StreamURLPrefixInt
};

if (command.FormFile != null)
Expand Down
27 changes: 9 additions & 18 deletions StreamMasterApplication/M3UFiles/Commands/UpdateM3UFileRequest.cs
Original file line number Diff line number Diff line change
@@ -1,31 +1,16 @@
using FluentValidation;

using StreamMasterDomain.Models;

namespace StreamMasterApplication.M3UFiles.Commands;
namespace StreamMasterApplication.M3UFiles.Commands;

public class UpdateM3UFileRequest : BaseFileRequest, IRequest<M3UFile?>
{
//public int? StreamURLPrefixInt { get; set; }
public int? MaxStreamCount { get; set; }
public int? StartingChannelNumber { get; set; }
}

public class UpdateM3UFileRequestValidator : AbstractValidator<UpdateM3UFileRequest>
{
public UpdateM3UFileRequestValidator()
{
_ = RuleFor(v => v.Id).NotNull().GreaterThanOrEqualTo(0);
}
}


[LogExecutionTimeAspect]
public class UpdateM3UFileRequestHandler : BaseMediatorRequestHandler, IRequestHandler<UpdateM3UFileRequest, M3UFile?>
public class UpdateM3UFileRequestHandler(ILogger<UpdateM3UFileRequest> logger, IRepositoryWrapper repository, IMapper mapper, ISettingsService settingsService, IPublisher publisher, ISender sender, IHubContext<StreamMasterHub, IStreamMasterHub> hubContext, IMemoryCache memoryCache) : BaseMediatorRequestHandler(logger, repository, mapper, settingsService, publisher, sender, hubContext, memoryCache), IRequestHandler<UpdateM3UFileRequest, M3UFile?>
{

public UpdateM3UFileRequestHandler(ILogger<UpdateM3UFileRequest> logger, IRepositoryWrapper repository, IMapper mapper, ISettingsService settingsService, IPublisher publisher, ISender sender, IHubContext<StreamMasterHub, IStreamMasterHub> hubContext, IMemoryCache memoryCache)
: base(logger, repository, mapper, settingsService, publisher, sender, hubContext, memoryCache) { }

public async Task<M3UFile?> Handle(UpdateM3UFileRequest request, CancellationToken cancellationToken)
{
try
Expand All @@ -45,6 +30,12 @@ public UpdateM3UFileRequestHandler(ILogger<UpdateM3UFileRequest> logger, IReposi
m3uFile.Description = request.Description;
}

//if (request.StreamURLPrefixInt != null && m3uFile.StreamURLPrefix != (M3UFileStreamURLPrefix)request.StreamURLPrefixInt)
//{
// isChanged = true;
// m3uFile.StreamURLPrefix = (M3UFileStreamURLPrefix)request.StreamURLPrefixInt;
//}

if (!string.IsNullOrEmpty(request.Url) && m3uFile.Url != request.Url)
{
isChanged = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,13 @@ public async Task UpdateM3UFile(UpdateM3UFileRequest request)

public async Task<PagedResponse<M3UFileDto>> GetPagedM3UFiles(M3UFileParameters m3uFileParameters)
{
PagedResponse<M3UFileDto> data = await mediator.Send(new GetPagedM3UFiles(m3uFileParameters)).ConfigureAwait(false);
return data;
return await mediator.Send(new GetPagedM3UFiles(m3uFileParameters)).ConfigureAwait(false);
}

public async Task<M3UFileDto?> GetM3UFile(int id)
{
M3UFileDto? data = await mediator.Send(new GetM3UFileByIdQuery(id)).ConfigureAwait(false);
return await mediator.Send(new GetM3UFileByIdQuery(id)).ConfigureAwait(false);

return data;
}

public async Task<List<string>> GetM3UFileNames()
Expand Down
2 changes: 1 addition & 1 deletion StreamMasterDomain/Dto/M3UFileDto.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class M3UFileDto : BaseFileDto, IMapFrom<M3UFile>
{
public int StartingChannelNumber { get; set; }
public int MaxStreamCount { get; set; }

//public M3UFileStreamURLPrefix StreamURLPrefix { get; set; }
public int StationCount { get; set; }

}
8 changes: 8 additions & 0 deletions StreamMasterDomain/Enums/M3UFileStreamURLPrefix.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace StreamMasterDomain.Enums;

//public enum M3UFileStreamURLPrefix
//{
// SystemDefault = 0,
// TS = 1,
// M3U8 = 2,
//}
4 changes: 2 additions & 2 deletions StreamMasterDomain/Models/M3UFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public M3UFile()
public int MaxStreamCount { get; set; }
public int StartingChannelNumber { get; set; }
public int StationCount { get; set; }

//public M3UFileStreamURLPrefix StreamURLPrefix { get; set; }
public DateTime LastWrite()
{
string fileName = Path.Combine(FileDefinitions.M3U.DirectoryLocation, Source);
Expand All @@ -36,7 +36,7 @@ public DateTime LastWrite()
lock (Lock)
{
using Stream dataStream = FileUtil.GetFileDataStream(Path.Combine(FileDefinitions.M3U.DirectoryLocation, Source));
var ret = IPTVExtensions.ConvertToVideoStream(dataStream, Id, Name);
List<VideoStream>? ret = IPTVExtensions.ConvertToVideoStream(dataStream, Id, Name);
dataStream.Close();
dataStream.Dispose();
return ret;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.HasKey("Id");
b.ToTable("DataProtectionKeys");
b.ToTable("DataProtectionKeys", (string)null);
});

modelBuilder.Entity("StreamMasterDomain.Models.ChannelGroup", b =>
Expand Down Expand Up @@ -62,7 +62,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.HasIndex("Name", "IsHidden")
.HasDatabaseName("idx_Name_IsHidden");
b.ToTable("ChannelGroups");
b.ToTable("ChannelGroups", (string)null);
});

modelBuilder.Entity("StreamMasterDomain.Models.EPGFile", b =>
Expand Down Expand Up @@ -135,7 +135,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.HasKey("Id");
b.ToTable("EPGFiles");
b.ToTable("EPGFiles", (string)null);
});

modelBuilder.Entity("StreamMasterDomain.Models.M3UFile", b =>
Expand Down Expand Up @@ -205,7 +205,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.HasKey("Id");
b.ToTable("M3UFiles");
b.ToTable("M3UFiles", (string)null);
});

modelBuilder.Entity("StreamMasterDomain.Models.StreamGroup", b =>
Expand All @@ -223,7 +223,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.HasKey("Id");
b.ToTable("StreamGroups");
b.ToTable("StreamGroups", (string)null);
});

modelBuilder.Entity("StreamMasterDomain.Models.StreamGroupChannelGroup", b =>
Expand All @@ -238,7 +238,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.HasIndex("StreamGroupId");
b.ToTable("StreamGroupChannelGroups");
b.ToTable("StreamGroupChannelGroups", (string)null);
});

modelBuilder.Entity("StreamMasterDomain.Models.StreamGroupVideoStream", b =>
Expand All @@ -259,7 +259,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.HasIndex("StreamGroupId");
b.ToTable("StreamGroupVideoStreams");
b.ToTable("StreamGroupVideoStreams", (string)null);
});

modelBuilder.Entity("StreamMasterDomain.Models.VideoStream", b =>
Expand Down Expand Up @@ -362,7 +362,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.HasIndex("User_Tvg_group", "IsHidden")
.HasDatabaseName("idx_User_Tvg_group_IsHidden");
b.ToTable("VideoStreams");
b.ToTable("VideoStreams", (string)null);
});

modelBuilder.Entity("StreamMasterDomain.Models.VideoStreamLink", b =>
Expand All @@ -380,7 +380,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.HasIndex("ChildVideoStreamId");
b.ToTable("VideoStreamLinks");
b.ToTable("VideoStreamLinks", (string)null);
});

modelBuilder.Entity("StreamMasterDomain.Models.StreamGroupChannelGroup", b =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ await FindByCondition(a => videoStreamIds.Contains(a.Id))
}
childVideoStreamDto.MaxStreams = result.MaxStreams;
childVideoStreamDto.M3UFileId = result.M3UFileId;

return (videoStream.VideoStreamHandler, new List<ChildVideoStreamDto> { childVideoStreamDto });
}

Expand Down
37 changes: 33 additions & 4 deletions StreamMasterInfrastructure/VideoStreamManager/ChannelManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ private int GetGlobalStreamsCount()

List<M3UFileDto> m3uFilesRepo = await repository.M3UFile.GetM3UFiles();

m3uFile = m3uFilesRepo.FirstOrDefault(a => a.Id == newVideoStream.M3UFileId);
m3uFile = m3uFilesRepo.Find(a => a.Id == newVideoStream.M3UFileId);
if (m3uFile == null)
{
if (GetGlobalStreamsCount() >= setting.GlobalStreamLimit)
Expand Down Expand Up @@ -323,15 +323,15 @@ private int GetGlobalStreamsCount()
if (result == null)
{
_logger.LogError("GetNextChildVideoStream could not get videoStream for id {VideoStreamId}", channelStatus.VideoStreamId);
_logger.LogDebug($"Exiting GetNextChildVideoStream with null due to result being null");
_logger.LogDebug("Exiting GetNextChildVideoStream with null due to result being null");
return null;
}

ChildVideoStreamDto[] videoStreams = result.Value.childVideoStreamDtos.OrderBy(a => a.Rank).ToArray();
if (!videoStreams.Any())
{
_logger.LogError("GetNextChildVideoStream could not get child videoStreams for id {VideoStreamId}", channelStatus.VideoStreamId);
_logger.LogDebug($"Exiting GetNextChildVideoStream with null due to no child videoStreams found");
_logger.LogDebug("Exiting GetNextChildVideoStream with null due to no child videoStreams found");
return null;
}

Expand All @@ -347,7 +347,7 @@ private int GetGlobalStreamsCount()
ChildVideoStreamDto toReturn = videoStreams[channelStatus.Rank++];
List<M3UFileDto> m3uFilesRepo = await repository.M3UFile.GetM3UFiles().ConfigureAwait(false);

m3uFile = m3uFilesRepo.FirstOrDefault(a => a.Id == toReturn.M3UFileId);
m3uFile = m3uFilesRepo.Find(a => a.Id == toReturn.M3UFileId);
if (m3uFile == null)
{
if (GetGlobalStreamsCount() >= setting.GlobalStreamLimit)
Expand All @@ -367,6 +367,11 @@ private int GetGlobalStreamsCount()
_logger.LogInformation("Max stream count {MaxStreams} reached for stream: {StreamUrl}", toReturn.MaxStreams, toReturn.User_Url);
continue;
}

//if (m3uFile.StreamURLPrefix != M3UFileStreamURLPrefix.SystemDefault)
//{
// toReturn.User_Url = ChangeExtensionBasedOnEnum(toReturn.User_Url, m3uFile.StreamURLPrefix);
//}
}

_logger.LogDebug($"Exiting GetNextChildVideoStream with toReturn: {toReturn}");
Expand All @@ -377,6 +382,30 @@ private int GetGlobalStreamsCount()
return null;
}

//public static string ChangeExtensionBasedOnEnum(string originalUrl, M3UFileStreamURLPrefix prefix)
//{
// Uri uri = new(originalUrl);
// string filename = Path.GetFileName(uri.LocalPath);
// string newFilename = "";

// switch (prefix)
// {
// case M3UFileStreamURLPrefix.SystemDefault:
// newFilename = filename;
// break;

// case M3UFileStreamURLPrefix.TS:
// newFilename = System.IO.Path.ChangeExtension(filename, ".ts");
// break;

// case M3UFileStreamURLPrefix.M3U8:
// newFilename = System.IO.Path.ChangeExtension(filename, ".m3u8");
// break;
// }

// return originalUrl.Replace(filename, newFilename);
//}

private async Task<bool> HandleNextVideoStream(ChannelStatus channelStatus, string? overrideNextVideoStreamId = null)
{
_logger.LogDebug($"Starting HandleNextVideoStream with channelStatus: {channelStatus} and overrideNextVideoStreamId: {overrideNextVideoStreamId}");
Expand Down
8 changes: 4 additions & 4 deletions streammasterwebui/app/SideBar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use client';
import MenuItemSM from '@/components/MenuItemSM';
import MenuItemSM from '@components/MenuItemSM';
import {
FilesEditorIcon,
HelpIcon,
Expand All @@ -10,9 +10,9 @@ import {
SideBarMenuIcon,
StreamGroupEditorIcon,
StreamingStatusIcon,
} from '@/lib/common/icons';
import { useSettingsGetSettingQuery } from '@/lib/iptvApi';
import useSettings from '@/lib/useSettings';
} from '@lib/common/icons';
import { useSettingsGetSettingQuery } from '@lib/iptvApi';
import useSettings from '@lib/useSettings';
import { useLocalStorage } from 'primereact/hooks';
import { Tooltip } from 'primereact/tooltip';
import React from 'react';
Expand Down
2 changes: 1 addition & 1 deletion streammasterwebui/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Providers } from '@/lib/providers';
import { Providers } from '@lib/providers';
import '@lib/styles/dataSelector.css';
import '@lib/styles/index.css';
import '@lib/styles/theme.css'; // theme
Expand Down
Loading

0 comments on commit 010e070

Please sign in to comment.