├── .all-contributorsrc ├── .devcontainer ├── Dockerfile.dev ├── devcontainer.json └── development-docker-compose.yml ├── .dockerignore ├── .gitattributes ├── .github ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug_report.yaml │ └── config.yml ├── SECURITY.md ├── labeler.yml ├── pull_request_template.md ├── release-drafter.yml └── workflows │ ├── Deploy_Documentation.yml │ ├── docker-build-shared.yml │ ├── mirror-to-docker-hub.yml │ ├── pr-build.yml │ ├── pr-cleanup.yml │ └── release-build.yml ├── .gitignore ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── 2025-02-12.png ├── CHANGELOG.md ├── Directory.Build.props ├── Dockerfile.base ├── Dockerfile.build ├── Dockerfile.sm.template ├── Dockerfile.template ├── Dockerfile.tests ├── LICENSE ├── README.md ├── StreamMaster.sln ├── docker-compose.yml ├── package-lock.json ├── package.json ├── release.config.norelease.cjs ├── release.config.release.cjs └── src ├── BuildClientAPI ├── BuildClientAPI.csproj ├── CSharp │ ├── CSharpGenerator.cs │ ├── CSharpUtils.cs │ └── DataRefreshService.cs ├── Models │ └── MethodDetails.cs ├── Program.cs ├── TS │ ├── SignalRGenerator.cs │ ├── SignalRGeneratorDataRefreshAll.cs │ ├── StoreGenerator.cs │ ├── StringExtensions.cs │ ├── TypeScriptCommandGenerator.cs │ ├── TypeScriptFetchGenerator.cs │ ├── TypeScriptHookGenerator.cs │ └── TypeScriptSliceGenerator.cs ├── TypeStandardizer.cs └── Utils.cs ├── Get-AssemblyInfo.ps1 ├── StreamMaster.API ├── .config │ └── dotnet-tools.json ├── AssemblyInfo.cs ├── ConfigureServices.cs ├── Controllers │ ├── APIKeysController.cs │ ├── AuthenticationController.cs │ ├── DevicesController.cs │ ├── FilesController.cs │ ├── MiscController.cs │ ├── SsController.cs │ ├── TestController.cs │ └── VController.cs ├── Exceptions │ ├── ApiException.cs │ ├── InvalidApiKeyException.cs │ └── ModelNotFoundException.cs ├── Fonts │ └── Roboto-Regular.ttf ├── GlobalUsings.cs ├── Helpers │ └── StreamUtil.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── Reinforced.Typings.settings.xml ├── ReinforcedTypingsConfiguration.cs ├── RoutePrefixConvention.cs ├── SchemaHelpers │ └── InheritanceSchemaProcessor.cs ├── Services │ ├── CurrentUserService.cs │ └── PostStartup.cs ├── StreamMaster.API.csproj ├── appsettings.Development.json ├── appsettings.Production.json ├── appsettings.json ├── hlssettings.Development.json ├── hlssettings.Production.json ├── hlssettings.json ├── libman.json ├── logsettings.Development.json ├── logsettings.Production.json ├── logsettings.json ├── nswag.json └── wwwroot │ └── images │ ├── default.png │ ├── streammaster_logo.png │ └── transparent.png ├── StreamMaster.Application ├── ChannelGroups │ ├── ChannelGroupService.cs │ ├── Commands │ │ ├── CreateChannelGroupRequest.cs │ │ ├── DeleteAllChannelGroupsFromParametersRequest.cs │ │ ├── DeleteChannelGroupRequest.cs │ │ ├── DeleteChannelGroupsRequest.cs │ │ ├── UpdateChannelGroupRequest.cs │ │ └── UpdateChannelGroupsRequest.cs │ ├── ControllerAndHub.cs │ ├── EventHandlers │ │ ├── UpdateChannelGroupEventHandler.cs │ │ └── UpdateChannelGroupsEventHandler.cs │ ├── Events │ │ ├── UpdateChannelGroupEvent.cs │ │ └── UpdateChannelGroupsEvent.cs │ ├── IControllerAndHub.cs │ └── Queries │ │ ├── GetChannelGroupByNameRequest.cs │ │ ├── GetChannelGroupRequest.cs │ │ ├── GetChannelGroupsFromSMChannelsRequest.cs │ │ ├── GetChannelGroupsRequest.cs │ │ └── GetPagedChannelGroupsRequest.cs ├── Common │ ├── ApiControllerBase.cs │ ├── AppHelper.cs │ ├── Behaviours │ │ ├── LoggingBehaviour.cs │ │ ├── UnhandledExceptionBehaviour.cs │ │ └── ValidationBehaviour.cs │ ├── Events │ │ ├── EPGFileAddedEvent.cs │ │ ├── EPGFileDeletedEvent.cs │ │ ├── M3UFileChangedEvent.cs │ │ └── M3UFileProcessEvent.cs │ ├── Extensions │ │ ├── HttpContextAccessorExtensions.cs │ │ └── RequestExtensions.cs │ ├── ImageConverter.cs │ ├── Models │ │ ├── BackgroundTaskQueueConfig.cs │ │ ├── Capability.cs │ │ ├── ChannelNumberPair.cs │ │ ├── Device.cs │ │ ├── Discover.cs │ │ ├── LineupStatus.cs │ │ ├── Result.cs │ │ ├── SpecVersion.cs │ │ └── VideoStreamIdRank.cs │ └── VersionedApiControllerAttribute.cs ├── ConfigureServices.cs ├── Crypto │ └── CryptoService.cs ├── Custom │ ├── Commands │ │ └── ScanForCustomRequest.cs │ ├── ControllerAndHub.cs │ ├── IControllerAndHub.cs │ ├── ICustomPlayListsInterfaces.cs │ └── Queries │ │ ├── GetCustomPlayListRequest.cs │ │ ├── GetCustomStreamsRequest.cs │ │ └── GetIntroPlayListsRequest.cs ├── EPG │ ├── Commands │ │ ├── EPGSyncRequest.cs │ │ └── XMLTVBuilder.cs │ ├── ControllerAndHub.cs │ ├── EPGService.cs │ ├── IControllerAndHub.cs │ └── Queries │ │ └── GetEPGColorsRequest.cs ├── EPGFiles │ ├── Commands │ │ ├── CreateEPGFileFromFormRequest.cs │ │ ├── CreateEPGFileRequest.cs │ │ ├── DeleteEPGFileRequest.cs │ │ ├── ProcessEPGFileRequest.cs │ │ ├── RefreshEPGFileRequest.cs │ │ ├── ScanDirectoryForEPGsRequest.cs │ │ └── UpdateEPGFileRequest.cs │ ├── ControllerAndHub.cs │ ├── Controllers │ │ └── EPGFilesController.cs │ ├── EPGFileService.cs │ ├── EventHandlers │ │ └── EPGFileAddedEventHandler.cs │ ├── IControllerAndHub.cs │ ├── IEPGInterfaces.cs │ └── Queries │ │ ├── GetEPGFileNamesRequest.cs │ │ ├── GetEPGFilePreviewByIdRequest.cs │ │ ├── GetEPGFilesRequest.cs │ │ ├── GetEPGNextEPGNumberRequest.cs │ │ └── GetPagedEPGFilesRequest.cs ├── General │ ├── Commands │ │ └── SetTestTaskRequest.cs │ ├── ControllerAndHub.cs │ └── IControllerAndHub.cs ├── GlobalSuppressions.cs ├── GlobalUsings.cs ├── Hub │ └── StreamMasterHub.cs ├── IBaseRequestHandler.cs ├── Interfaces │ ├── IChannelGroupService.cs │ ├── ICryptoService.cs │ ├── ICurrentUserService.cs │ ├── IDateTime.cs │ ├── IEPGFileService.cs │ ├── IFeatureFlagService.cs │ ├── IM3UToSMStreamsService.cs │ ├── ISharedInterfaces.cs │ ├── IStreamGroupService.cs │ └── IStreamMasterHub.cs ├── Logos │ ├── Commands │ │ ├── AddCustomLogoRequest.cs │ │ ├── CacheEPGChannelLogosRequest.cs │ │ ├── CacheSMChannelLogosRequest.cs │ │ ├── CacheSMStreamLogosRequest.cs │ │ └── RemoveCustomLogoRequest.cs │ ├── ControllerAndHub.cs │ ├── IControllerAndHub.cs │ ├── ILogoInterfaces.cs │ └── Queries │ │ ├── GetCustomLogosRequest.cs │ │ ├── GetLogoForChannelRequest.cs │ │ ├── GetLogoRequest.cs │ │ ├── GetLogosRequest.cs │ │ └── Helper.cs ├── Logs │ ├── ControllerAndHub.cs │ ├── IControllerAndHub.cs │ └── Queries │ │ ├── GetLogContentsRequest.cs │ │ └── GetLogNamesRequest.cs ├── M3UFiles │ ├── Commands │ │ ├── CreateM3UFileFromFormRequest.cs │ │ ├── CreateM3UFileRequest.cs │ │ ├── DeleteM3UFileRequest.cs │ │ ├── ProcessM3UFileRequest.cs │ │ ├── ProcessM3UFilesRequest.cs │ │ ├── RefreshM3UFileRequest.cs │ │ ├── ScanDirectoryForM3UsRequest.cs │ │ ├── SyncChannelsRequest.cs │ │ └── UpdateM3UFileRequest.cs │ ├── ControllerAndHub.cs │ ├── Controllers │ │ └── M3UFilesController.cs │ ├── EventHandlers │ │ ├── M3UFileChangedEventHandler.cs │ │ └── M3UFileProcessEventHandler.cs │ ├── IControllerAndHub.cs │ ├── IM3UInterfaces.cs │ ├── M3UFileService.cs │ ├── M3UtoSMStreamsService.cs │ └── Queries │ │ ├── GetM3UFileNamesRequest.cs │ │ ├── GetM3UFilesRequest.cs │ │ └── GetPagedM3UFilesRequest.cs ├── Profiles │ ├── Commands │ │ ├── AddCommandProfileRequest.cs │ │ ├── AddOutputProfileRequest.cs │ │ ├── RemoveCommandProfileRequest.cs │ │ ├── RemoveOutputProfileRequest.cs │ │ ├── UpdateCommandProfileRequest.cs │ │ └── UpdateOutputProfileRequest.cs │ ├── ControllerAndHub.cs │ ├── IControllerAndHub.cs │ └── Queries │ │ ├── GetCommandProfilesRequest.cs │ │ ├── GetOutputProfileRequest.cs │ │ └── GetOutputProfilesRequest.cs ├── Properties │ └── launchSettings.json ├── SMChannelChannelLinks │ ├── Commands │ │ ├── AddSMChannelToSMChannelRequest.cs │ │ ├── RemoveSMChannelFromSMChannelRequest.cs │ │ ├── SetSMChannelRanksRequest.cs │ │ └── UpdateSMChannelRanksRequest.cs │ ├── ControllerAndHub.cs │ ├── IControllerAndHub.cs │ └── Queries │ │ └── GetSMChannelChannelsRequest.cs ├── SMChannelStreamLinks │ ├── Commands │ │ ├── AddSMStreamToSMChannelRequest.cs │ │ ├── RemoveSMStreamFromSMChannelRequest.cs │ │ ├── SetSMStreamRanksRequest.cs │ │ └── UpdateStreamRanksRequest.cs │ ├── ControllerAndHub.cs │ ├── IControllerAndHub.cs │ └── Queries │ │ └── GetSMChannelStreamsRequest.cs ├── SMChannels │ ├── Commands │ │ ├── AutoSetEPGFromParametersRequest.cs │ │ ├── AutoSetEPGRequest.cs │ │ ├── AutoSetSMChannelNumbersFromParametersRequest.cs │ │ ├── AutoSetSMChannelNumbersRequest.cs │ │ ├── CopySMChannelRequest.cs │ │ ├── CreateMultiViewChannelRequest.cs │ │ ├── CreateSMChannelRequest.cs │ │ ├── CreateSMChannelsFromStreamParametersRequest.cs │ │ ├── CreateSMChannelsFromStreamsRequest.cs │ │ ├── DeleteSMChannelRequest.cs │ │ ├── DeleteSMChannelsFromParametersRequest.cs │ │ ├── DeleteSMChannelsRequest.cs │ │ ├── SetSMChannelEPGIDRequest.cs │ │ ├── SetSMChannelGroupRequest.cs │ │ ├── SetSMChannelLogoRequest.cs │ │ ├── SetSMChannelNameRequest.cs │ │ ├── SetSMChannelNumberRequest.cs │ │ ├── SetSMChannelVideoOutputProfileNameRequest.cs │ │ ├── SetSMChannelsGroupFromParametersRequest.cs │ │ ├── SetSMChannelsGroupRequest.cs │ │ ├── SetSMChannelsLogoFromEPGFromParametersRequest.cs │ │ ├── SetSMChannelsLogoFromEPGRequest.cs │ │ ├── SetSMChannelsVideoOutputProfileNameFromParametersRequest.cs │ │ ├── SetSMChannelsVideoOutputProfileNameRequest.cs │ │ ├── ToggleSMChannelVisibleByIdRequest.cs │ │ ├── ToggleSMChannelVisibleByParametersRequest.cs │ │ ├── ToggleSMChannelsVisibleByIdRequest.cs │ │ ├── UpdateMultiViewChannelRequest.cs │ │ └── UpdateSMChannelRequest.cs │ ├── ControllerAndHub.cs │ ├── IControllerAndHub.cs │ ├── Queries │ │ ├── GetPagedSMChannelsRequest.cs │ │ ├── GetSMChannelUniqueNameRequest.cs │ │ └── IdNameUrl.cs │ └── SMChannelService.cs ├── SMMessages │ ├── Commands │ │ ├── SendSMErrorRequest.cs │ │ ├── SendSMInfoRequest.cs │ │ ├── SendSMMessageRequest.cs │ │ ├── SendSMWarnRequest.cs │ │ └── SendSuccessRequest.cs │ ├── ControllerAndHub.cs │ └── IControllerAndHub.cs ├── SMStreams │ ├── Commands │ │ ├── CreateSMStreamRequest.cs │ │ ├── DeleteSMStreamRequest.cs │ │ ├── SetSMStreamsVisibleByIdRequest.cs │ │ ├── ToggleSMStreamVisibleByIdRequest.cs │ │ ├── ToggleSMStreamVisibleByParametersRequest.cs │ │ ├── ToggleSMStreamsVisibleByIdRequest.cs │ │ └── UpdateSMStreamRequest.cs │ ├── ControllerAndHub.cs │ ├── IControllerAndHub.cs │ ├── Queries │ │ └── GetPagedSMStreamsRequest.cs │ └── SMStreamService.cs ├── SMTasks │ ├── Commands │ │ └── SendSMTaskRequest.cs │ ├── ControllerAndHub.cs │ ├── IControllerAndHub.cs │ └── Queries │ │ └── GetSMTasksRequest.cs ├── SchedulesDirect │ ├── Commands │ │ ├── AddHeadendToViewRequest.cs │ │ ├── AddLineupRequest.cs │ │ ├── AddStationRequest.cs │ │ ├── EPGRemovedExpiredKeysRequest.cs │ │ ├── EPGSync.cs │ │ ├── RemoveHeadendToViewRequest.cs │ │ ├── RemoveLineupRequest.cs │ │ ├── RemoveStationRequest.cs │ │ └── SetStationsRequest.cs │ ├── ControllerAndHub.cs │ ├── IControllerAndHub.cs │ └── Queries │ │ ├── GetAvailableCountriesRequest.cs │ │ ├── GetChannelNamesRequest.cs │ │ ├── GetHeadendsByCountryPostalRequest.cs │ │ ├── GetHeadendsToViewRequest.cs │ │ ├── GetLineupPreviewChannelRequest.cs │ │ ├── GetPagedStationChannelNameSelections.cs │ │ ├── GetSelectedStationIdsRequest.cs │ │ ├── GetStationChannelNamesRequest.cs │ │ ├── GetStationPreviewsRequest.cs │ │ ├── GetSubScribedHeadendsRequest.cs │ │ └── GetSubscribedLineupsRequest.cs ├── Services │ ├── FeatureFlagService.cs │ └── IBackgroundTaskQueue.cs ├── Settings │ ├── Commands │ │ ├── UpdateSettingParameters.cs │ │ └── UpdateSettingRequest.cs │ ├── ControllerAndHub.cs │ ├── Hub │ │ └── StreamMasterHub.Setting.cs │ ├── IControllerAndHub.cs │ ├── ISettingInterfaces.cs │ ├── LogInRequest.cs │ └── Queries │ │ └── GetSettingsRequest.cs ├── Statistics │ ├── Commands │ │ └── SetIsSystemReadyRequest.cs │ ├── ControllerAndHub.cs │ ├── IControllerAndHub.cs │ └── Queries │ │ ├── GetChannelMetricsRequest.cs │ │ ├── GetDownloadServiceStatusRequest.cs │ │ ├── GetIsSystemReadyRequest.cs │ │ ├── GetStreamConnectionMetricRequest.cs │ │ ├── GetStreamConnectionMetricsRequest.cs │ │ ├── GetSystemStatusRequest.cs │ │ ├── GetTaskIsRunningRequest.cs │ │ ├── GetVideoInfoRequest.cs │ │ └── GetVideoInfosRequest.cs ├── StreamGroupSMChannelLinks │ ├── Commands │ │ ├── AddSMChannelToStreamGroupRequest.cs │ │ ├── AddSMChannelsToStreamGroupByParametersRequest.cs │ │ ├── AddSMChannelsToStreamGroupRequest.cs │ │ ├── MoveSMChannelsToStreamGroupByM3UFileIdRequest.cs │ │ └── RemoveSMChannelFromStreamGroupRequest.cs │ ├── ControllerAndHub.cs │ ├── IControllerAndHub.cs │ └── Queries │ │ └── GetStreamGroupSMChannelsRequest.cs ├── StreamGroups │ ├── Commands │ │ ├── AddProfileToStreamGroupRequest.cs │ │ ├── CreateSTRMFilesRequest.cs │ │ ├── CreateStreamGroupRequest.cs │ │ ├── DeleteStreamGroupRequest.cs │ │ ├── RemoveStreamGroupProfileRequest.cs │ │ ├── UpdateStreamGroupProfileRequest.cs │ │ └── UpdateStreamGroupRequest.cs │ ├── ControllerAndHub.cs │ ├── Controllers │ │ └── StreamGroupsController.cs │ ├── IControllerAndHub.cs │ ├── IStreamGroupInterfaces.cs │ ├── Queries │ │ ├── GetPagedStreamGroups.cs │ │ ├── GetStreamGroupEPG.cs │ │ ├── GetStreamGroupM3U.cs │ │ ├── GetStreamGroupProfilesRequest.cs │ │ ├── GetStreamGroupRequest.cs │ │ └── GetStreamGroupsRequest.cs │ ├── SMFile.cs │ └── StreamGroupService.cs ├── StreamMaster.Application.csproj ├── Streaming │ ├── Commands │ │ ├── CancelAllChannelsRequest.cs │ │ ├── CancelChannelRequest.cs │ │ ├── CancelClientRequest.cs │ │ └── MoveToNextStreamRequest.cs │ ├── ControllerAndHub.cs │ └── IControllerAndHub.cs ├── Vs │ ├── ControllerAndHub.cs │ ├── IControllerAndHub.cs │ └── Queries │ │ └── GetVsRequest.cs └── WebSocket │ ├── Commands │ └── TriggerReloadRequest.cs │ ├── ControllerAndHub.cs │ └── IControllerAndHub.cs ├── StreamMaster.Docs ├── prompt.md ├── requirements.txt └── streammaster │ ├── .gitignore │ ├── contributors.py │ ├── docs │ ├── assets │ │ ├── AddHDHR.png │ │ ├── ConfigureHDHR.png │ │ ├── SetXML.png │ │ ├── profiles.png │ │ ├── sm.png │ │ └── sm_logo.png │ ├── en │ │ ├── Auth.md │ │ ├── BackupRestore.md │ │ ├── CommandProfiles.md │ │ ├── Contributors.md │ │ ├── Docs.md │ │ ├── EPG.md │ │ ├── GettingStarted.md │ │ ├── M3U.md │ │ ├── M3U_Output_Attributes.md │ │ ├── OutputProfiles.md │ │ ├── SD.md │ │ ├── Settings.md │ │ ├── StreamGroup.md │ │ ├── image.png │ │ └── index.md │ └── includes │ │ └── _footer.md │ └── mkdocs.yml ├── StreamMaster.Domain ├── API │ ├── APIResponse.cs │ ├── DataResponse.cs │ ├── NoClass.cs │ └── PagedResponse.cs ├── Attributes │ ├── BuilderIgnore.cs │ ├── CreateDirAttribute.cs │ ├── IgnoreMapAttribute.cs │ ├── IndexBy.cs │ ├── JustUpdates.cs │ ├── RequireAll.cs │ ├── SMAPI.cs │ └── SortBy.cs ├── Authentication │ └── IUserRepository.cs ├── Cache │ ├── ISMCache.cs │ └── SMCacheManager.cs ├── Color │ └── ColorHelper.cs ├── Common │ ├── BaseEntity.cs │ ├── BaseEvent.cs │ ├── CuidConverter.cs │ ├── FileUtil.cs │ ├── M3UFileIdMaxStream.cs │ ├── ProxyStreamErrorCode.cs │ ├── SGLineUp.cs │ ├── ThreadSafeCounter.cs │ ├── ThreadSafeIntList.cs │ ├── UpdateSettingResponse.cs │ ├── Utf8StringWriter.cs │ └── Utils.cs ├── Comparer │ └── NumericStringComparer.cs ├── Compression │ └── CompressionUtils.cs ├── Configuration │ ├── AlphabeticalJsonTypeInfoResolver.cs │ ├── BuildInfo.cs │ ├── CommandProfile.cs │ ├── CustomLogo.cs │ ├── ErrorCooldownSetting.cs │ ├── HLSSettings.cs │ ├── IProfileDict.cs │ ├── OutputProfile.cs │ ├── SDSettings.cs │ ├── SDSettingsRequest.cs │ ├── Setting.cs │ └── SettingFiles.cs ├── Crypto │ ├── AesEncryption.cs │ ├── Base32Extensions.cs │ ├── Base64Extensions.cs │ ├── CryptoHelpers.cs │ ├── CryptoUtils.cs │ ├── FNV1aHasher.cs │ ├── Hashing.cs │ ├── KeyGenerator.cs │ └── StringExtensions.cs ├── Dto │ ├── BaseFileDto.cs │ ├── ChannelGroupDto.cs │ ├── ChannelGroupIdName.cs │ ├── ChannelLogoDto.cs │ ├── EPGColor.cs │ ├── EPGFileDto.cs │ ├── EPGFilePreviewDto.cs │ ├── GetChannelGroupVideoStreamCountResponse.cs │ ├── IDVisible.cs │ ├── IdName.cs │ ├── LogEntryDto.cs │ ├── LogoDto.cs │ ├── LogoInfo.cs │ ├── M3UFileDto.cs │ ├── PagedDto.cs │ ├── SDSystemStatus.cs │ ├── SMChannelDto.cs │ ├── SMStreamDto.cs │ ├── SettingDto.cs │ ├── StreamGroupDto.cs │ ├── StreamingServiceStatusDto.cs │ └── VideoStreamIsReadOnly.cs ├── Enums │ ├── AuthenticationType.cs │ ├── FeatureFlags.cs │ ├── FileDefinition.cs │ ├── FileDefinitions.cs │ ├── JobType.cs │ ├── M3UField.cs │ ├── M3UFileStreamURLPrefix.cs │ ├── M3UKey.cs │ ├── SMChannelTypeEnum.cs │ ├── SMFileTypes.cs │ ├── SMQueCommand.cs │ ├── SMStreamTypeEnum.cs │ ├── ValidM3USetting.cs │ └── VideoStreamHandlers.cs ├── EnvironmentInfo │ └── OsInfo.cs ├── Events │ └── AsyncEventHandler.cs ├── Exceptions │ ├── APIException.cs │ └── EnumerableExtensions.cs ├── Extensions │ ├── ConcurrentBagExtensions.cs │ ├── ConcurrentDictionaryExtensions.cs │ ├── ConcurrentHashSet.cs │ ├── CustomLogoDtoComparer.cs │ ├── DateTimeExtensions.cs │ ├── DictionaryExtensions.cs │ ├── EnumExtensions.cs │ ├── HttpClientExtensions.cs │ ├── ImageExtensions.cs │ ├── ListComparer.cs │ ├── ListHelper.cs │ ├── MiscExtentions.cs │ ├── PagedExtensions.cs │ ├── StringExtensions.cs │ ├── TaskCompletionSourceExtensions.cs │ ├── TokenExtensions.cs │ ├── UniqueHexGenerator.cs │ └── VideoInfoExtensions.cs ├── Filtering │ ├── DataTableFilterMetaData.cs │ └── FilterHelper.cs ├── GlobalUsings.cs ├── Helpers │ ├── DebugAPIHelper.cs │ ├── DirectoryHelper.cs │ ├── EPGHelper.cs │ ├── EPGNumberStationIdExtension.cs │ ├── ParseFlexibleDateHelper.cs │ ├── ProcesHelper.cs │ └── SettingsHelper.cs ├── Logging │ ├── CustomLogger.cs │ ├── GlobalLoggerProvider.cs │ ├── ILoggingUtils.cs │ ├── LogExecutionTimeAttribute.cs │ └── LoggingUtils.cs ├── Mappings │ ├── IMapFrom.cs │ └── MappingProfile.cs ├── Models │ ├── APIKey.cs │ ├── APIKeyResponse.cs │ ├── AddSMStreamToSMChannelRequest.cs │ ├── AutoUpdateEntity.cs │ ├── CacheEntry.cs │ ├── ChannelGroup.cs │ ├── CreateAPIKeyRequest.cs │ ├── Device.cs │ ├── DeviceResponse.cs │ ├── DupInfo.cs │ ├── EPGFile.cs │ ├── FieldData.cs │ ├── HeadendToView.cs │ ├── IM3UStream.cs │ ├── IPTVFile.cs │ ├── ISMStreamInfo.cs │ ├── IconFile.cs │ ├── IdIntResultWithResponse.cs │ ├── ImageDownloadServiceStatus.cs │ ├── ImagePath.cs │ ├── JobStatus.cs │ ├── JobStatusManager.cs │ ├── LogEntry.cs │ ├── M3UFile.cs │ ├── M3UGroup.cs │ ├── ProgrammeChannel.cs │ ├── SDCacheEntry.cs │ ├── SMChannel.cs │ ├── SMChannelChannelLink.cs │ ├── SMChannelStreamLink.cs │ ├── SMMessage.cs │ ├── SMStream.cs │ ├── SMStreamInfo.cs │ ├── SMTask.cs │ ├── StationIdLineUp.cs │ ├── StreamAccessInfo.cs │ ├── StreamGroup.cs │ ├── StreamGroupChannelGroup.cs │ ├── StreamGroupProfile.cs │ ├── StreamGroupSMChannelLink.cs │ ├── SystemKeyValue.cs │ ├── TvLogoFile.cs │ ├── User.cs │ ├── UserGroup.cs │ ├── VideoInfo.cs │ ├── VideoStreamConfig.cs │ └── VideoStreamIDRank.cs ├── Pagination │ └── QueryStringParameters.cs ├── Properties │ └── launchSettings.json ├── Repository │ ├── IAPIKeyRepository.cs │ ├── IChannelGroupRepository.cs │ ├── IDeviceRepository.cs │ ├── IEPGFileRepository.cs │ ├── IM3UFileRepository.cs │ ├── IRepositoryBase.cs │ ├── IRepositoryContext.cs │ ├── IRepositoryWrapper.cs │ ├── ISMChannelsRepository.cs │ ├── ISMStreamRepository.cs │ ├── IStreamGroupChannelGroupRepository.cs │ ├── IStreamGroupRepository.cs │ └── IStreamGroupSMChannelLinkRepository.cs ├── Services │ ├── APIStatsLogger.cs │ ├── IAPIKeyService.cs │ ├── IAPIStatsLogger.cs │ ├── IBroadcastService.cs │ ├── IDataRefreshService.cs │ ├── IDeviceService.cs │ ├── IEPGHelper.cs │ ├── IEPGService.cs │ ├── IFileLoggingService.cs │ ├── IFileLoggingServiceFactory.cs │ ├── IFileUtilService.cs │ ├── IImageDownloadService.cs │ ├── IJobStatusService.cs │ ├── ILogoService.cs │ ├── IM3UFileService.cs │ ├── IMessageService.cs │ ├── IProfileService.cs │ ├── ISMChannelChannelLinksRepository.cs │ ├── ISMChannelService.cs │ ├── ISMChannelStreamLinksRepository.cs │ ├── ISMStreamService.cs │ ├── ISMWebSocketManager.cs │ ├── IStreamGroupProfileRepository.cs │ └── ProfileService.cs ├── Sorting │ └── ISortHelper.cs ├── StreamMaster.Domain.csproj ├── XML │ └── XMLUtil.cs └── XmltvXml │ ├── StationChannelName.cs │ ├── XMLTV.cs │ ├── XmltvActor.cs │ ├── XmltvAudio.cs │ ├── XmltvChannel.cs │ ├── XmltvCredit.cs │ ├── XmltvEpisodeNum.cs │ ├── XmltvIcon.cs │ ├── XmltvLength.cs │ ├── XmltvPreviouslyShown.cs │ ├── XmltvProgramme.cs │ ├── XmltvRating.cs │ ├── XmltvReview.cs │ ├── XmltvSubtitles.cs │ ├── XmltvText.cs │ └── XmltvVideo.cs ├── StreamMaster.EPG ├── ConfigureServices.cs ├── EpgMatcher.cs ├── IEpgMatcher.cs └── StreamMaster.EPG.csproj ├── StreamMaster.Infrastructure.EF.Base ├── BaseRepositoryContext.cs ├── Configurations │ ├── SMChannelChannelLinkConfiguration.cs │ ├── SMChannelStreamLinkConfiguration.cs │ ├── SMStreamConfiguration.cs │ ├── StreamGroupChannelGroupConfiguration.cs │ └── StreamGroupSMChannelLinkConfiguration.cs ├── GlobalUsings.cs └── StreamMaster.Infrastructure.EF.Base.csproj ├── StreamMaster.Infrastructure.EF.PGSQL.Console ├── Program.cs └── StreamMaster.Infrastructure.EF.PGSQL.Console.csproj ├── StreamMaster.Infrastructure.EF.PGSQL ├── Add-EfMigration.ps1 ├── ConfigureServices.cs ├── DesignTimeRepositoryContextFactory.cs ├── Migrations │ └── Repository │ │ ├── 20241018224015_Initial.Designer.cs │ │ ├── 20241018224015_Initial.cs │ │ ├── 20241215142948_AddedExtInf.Designer.cs │ │ ├── 20241215142948_AddedExtInf.cs │ │ ├── 20241216201039_SGSTRM.Designer.cs │ │ ├── 20241216201039_SGSTRM.cs │ │ ├── 20250214180110_AddUserGroups_M3UGroups_APIKeys_Devices_to_PGSQLRepositoryContext_to_PGSQLRepositoryContext.Designer.cs │ │ ├── 20250214180110_AddUserGroups_M3UGroups_APIKeys_Devices_to_PGSQLRepositoryContext_to_PGSQLRepositoryContext.cs │ │ ├── 20250217190832_M3UFileId.Designer.cs │ │ ├── 20250217190832_M3UFileId.cs │ │ └── PGSQLRepositoryContextModelSnapshot.cs ├── PGSQLRepositoryContext.cs ├── RemoveLast-EfMigration.ps1 ├── Scripts │ ├── 001_channelgroup_indexes.sql │ ├── 002_create_or_update_smstreams_and_channels.sql │ ├── 003_delete_sm_channels.sql │ ├── 004_epgfile_indexes.sql │ ├── 005_get_unique_smchannel_name.sql │ ├── 006_smchannel_indexes.sql │ ├── 007_smchannelstreamlink_indexes.sql │ ├── 008_smstream_indexes.sql │ ├── 009_streamgroup_indexes.sql │ ├── 010_streamgroupsmchannellink_indexes.sql │ ├── 011_update_channel_group_counts.sql │ └── 012_migrate_new_channel_ids.sql └── StreamMaster.Infrastructure.EF.PGSQL.csproj ├── StreamMaster.Infrastructure.EF ├── ConfigureServices.cs ├── GlobalUsings.cs ├── Helpers │ ├── AutoEPGMatch.cs │ └── SortHelper.cs ├── Repositories │ ├── APIKeyRepository.cs │ ├── ChannelGroupRepository.cs │ ├── DeviceRepository.cs │ ├── EPGFileRepository.cs │ ├── M3UFileRepository.cs │ ├── RepositoryBase.cs │ ├── SMChannelChannelLinksRepository.cs │ ├── SMChannelStreamLinksRepository.cs │ ├── SMChannelsRepository.cs │ ├── SMStreamRepository.cs │ ├── StreamGroupProfileRepository.cs │ ├── StreamGroupRepository.cs │ └── StreamGroupSMChannelLinkRepository.cs ├── RepositoryContextInitializer.cs ├── RepositoryWrapper.cs ├── StreamMaster.Infrastructure.EF.csproj └── ef_commands.ps1 ├── StreamMaster.Infrastructure ├── Authentication │ ├── APIKeyService.cs │ ├── ApiKeyAuthenticationOptions.cs │ ├── AuthenticationBuilderExtensions.cs │ ├── AuthenticationService.cs │ ├── DeviceService.cs │ ├── LoginResource.cs │ ├── NoAuthenticationHandler.cs │ └── UiAuthorizationPolicyProvider.cs ├── Common │ └── MediatorExtensions.cs ├── ConfigureServices.cs ├── Extensions │ ├── HttpContextExtensions.cs │ └── RequestExtensions.cs ├── GlobalSuppressions.cs ├── GlobalUsings.cs ├── Logger │ ├── FileLoggerDebug.cs │ ├── FileLoggerDebugProvider.cs │ ├── FileLoggingServiceFactory.cs │ ├── SMLogger.cs │ ├── SMLoggerProvider.cs │ └── StatsLogger.cs ├── Middleware │ └── CacheableSpecification.cs ├── Services │ ├── BroadcastService.cs │ ├── DataRefreshService.cs │ ├── Downloads │ │ ├── ImageDownloadQueue.cs │ │ └── ImageDownloadService.cs │ ├── FileLoggingService.cs │ ├── FileUtilService.cs │ ├── Frontend │ │ ├── Mappers │ │ │ ├── ConfigMapper.cs │ │ │ ├── FaviconMapper.cs │ │ │ ├── HtmlMapperBase.cs │ │ │ ├── IMapHttpRequestsToDisk.cs │ │ │ ├── ImagesMapper.cs │ │ │ ├── IndexHtmlMapper.cs │ │ │ ├── LoginHtmlMapper.cs │ │ │ ├── ManifestJsonMapper.cs │ │ │ ├── ManifestMapper.cs │ │ │ ├── NextStaticResourceMapper.cs │ │ │ ├── StaticResourceMapper.cs │ │ │ ├── StaticResourceMapperBase.cs │ │ │ ├── SwaggerMapper.cs │ │ │ └── ThemeMapper.cs │ │ └── StaticResourceController.cs │ ├── JobStatusService.cs │ ├── LogoService.cs │ ├── MessageService.cs │ ├── QueueService │ │ ├── BackgroundTaskQueue.CustomPlayList.cs │ │ ├── BackgroundTaskQueue.EPG.cs │ │ ├── BackgroundTaskQueue.Icons.cs │ │ ├── BackgroundTaskQueue.M3U.cs │ │ ├── BackgroundTaskQueue.STRM.cs │ │ ├── BackgroundTaskQueue.cs │ │ └── QueuedHostedService.cs │ ├── SMWebSocketManager.cs │ └── TimerService.cs └── StreamMaster.Infrastructure.csproj ├── StreamMaster.Logging ├── Loggers.cs └── StreamMaster.Logging.csproj ├── StreamMaster.PlayList ├── ConfigureServices.cs ├── CustomPlayListBuilder.cs ├── CustomStreamNfo.cs ├── ICustomPlayListBuilder.cs ├── IIntroPlayListBuilder.cs ├── INfoFileReader.cs ├── IntroPlayListBuilder.cs ├── Models │ ├── Actor.cs │ ├── Audio.cs │ ├── CustomPlayList.cs │ ├── Fanart.cs │ ├── Fileinfo.cs │ ├── Movie.cs │ ├── Rating.cs │ ├── Ratings.cs │ ├── Set.cs │ ├── Streamdetails.cs │ ├── Subtitle.cs │ ├── Thumb.cs │ ├── Uniqueid.cs │ └── Video.cs ├── NfoFileReader.cs └── StreamMaster.PlayList.csproj ├── StreamMaster.SchedulesDirect.Domain ├── Dto │ ├── HeadendDto.cs │ └── ProgrammeNameDto.cs ├── Enums │ ├── APIMethod.cs │ ├── ImageType.cs │ └── KeywordGroupsEnum.cs ├── Extensions │ └── MxfServiceExtensions.cs ├── GlobalUsings.cs ├── Interfaces │ ├── ICustomStreamData.cs │ ├── IDataPreparationService.cs │ ├── IDescriptionService.cs │ ├── IEPGCached.cs │ ├── IEpisodeImages.cs │ ├── IImageDownloadQueue.cs │ ├── ILineupService.cs │ ├── IMovieImages.cs │ ├── IProgramRepository.cs │ ├── IProgramService.cs │ ├── ISDXMLTVBuilder.cs │ ├── IScheduleService.cs │ ├── ISchedulesDirect.cs │ ├── ISchedulesDirectAPIService.cs │ ├── ISchedulesDirectData.cs │ ├── ISchedulesDirectDataService.cs │ ├── ISchedulesDirectHttpService.cs │ ├── ISeasonImages.cs │ ├── ISeriesImages.cs │ ├── ISportsImages.cs │ ├── IXMLTVBuilder.cs │ ├── IXmltv2Mxf.cs │ ├── IXmltvChannelBuilder.cs │ └── IXmltvProgramBuilder.cs ├── JsonClasses │ ├── AddRemoveLineups.cs │ ├── AvailableCountries.cs │ ├── BaseResponse.cs │ ├── GenericDescriptions.cs │ ├── HeadendLineup.cs │ ├── Headends.cs │ ├── JsonConverters.cs │ ├── LineupChannel.cs │ ├── LineupPreview.cs │ ├── LineupResponse.cs │ ├── ProgramArtwork.cs │ ├── ProgramAward.cs │ ├── ProgramContentRating.cs │ ├── ProgramDescription.cs │ ├── ProgramDescriptions.cs │ ├── ProgramEventDetails.cs │ ├── ProgramEventDetailsTeam.cs │ ├── ProgramKeyWords.cs │ ├── ProgramMetadata.cs │ ├── ProgramMetadataProvider.cs │ ├── ProgramMovie.cs │ ├── ProgramPerson.cs │ ├── ProgramQualityRating.cs │ ├── ProgramRecommendation.cs │ ├── ProgramTitle.cs │ ├── Programme.cs │ ├── ScheduleMd5Response.cs │ ├── ScheduleMetadata.cs │ ├── ScheduleMultipart.cs │ ├── ScheduleProgram.cs │ ├── ScheduleRequest.cs │ ├── ScheduleResponse.cs │ ├── ScheduleTvRating.cs │ ├── StationBroadcaster.cs │ ├── StatusAccount.cs │ ├── StatusLineup.cs │ ├── SubscribedLineup.cs │ ├── SystemStatus.cs │ ├── Token.cs │ ├── TokenResponse.cs │ └── UserStatus.cs ├── JsonConverters.cs ├── Models │ ├── BaseArt.cs │ ├── Broadcaster.cs │ ├── CountryData.cs │ ├── EPGJsonCache.cs │ ├── ImageInfo.cs │ ├── LineUpResult.cs │ ├── Lineup.cs │ ├── Logo.cs │ ├── Map.cs │ ├── Metadata.cs │ ├── MxfAffiliate.cs │ ├── MxfChannel.cs │ ├── MxfGuideImage.cs │ ├── MxfKeyword.cs │ ├── MxfKeywordGroup.cs │ ├── MxfLineup.cs │ ├── MxfPerson.cs │ ├── MxfPersonRank.cs │ ├── MxfProgram.cs │ ├── MxfProvider.cs │ ├── MxfScheduleEntries.cs │ ├── MxfScheduleEntry.cs │ ├── MxfService.cs │ ├── SDGetToken.cs │ ├── SDTokenFile.cs │ ├── Season.cs │ ├── SeriesInfo.cs │ ├── Station.cs │ └── StationPreview.cs ├── ResponseCodes.cs ├── SDAPIConfig.cs └── StreamMaster.SchedulesDirect.Domain.csproj ├── StreamMaster.SchedulesDirect.Services ├── ApiErrorManager.cs ├── ConfigureServices.cs ├── GlobalUsings.cs ├── ISchedulesDirectRepository.cs ├── SchedulesDirectAPIService.cs ├── SchedulesDirectHttpService.cs ├── SchedulesDirectRepository.cs ├── StreamMaster.SchedulesDirect.Services.csproj ├── TokenRefreshException.cs └── TokenValidationException.cs ├── StreamMaster.SchedulesDirect ├── ConfigureServices.cs ├── Converters │ ├── DataPreparationService.cs │ ├── SDXMLTVBuilder.cs │ ├── XmltvChannelBuilder.cs │ └── XmltvProgramBuilder.cs ├── Data │ ├── CustomStreamData.cs │ ├── MxfLineup.cs │ ├── MxfService.cs │ ├── SchedulesDirectData.cs │ └── SchedulesDirectDataService.cs ├── GlobalUsings.cs ├── Helpers │ ├── HashHelper.cs │ ├── SDExtensions.cs │ └── SDHelpers.cs ├── Images │ ├── EpisodeImages.cs │ ├── MovieImages.cs │ ├── SeasonImages.cs │ ├── SeriesImages.cs │ └── SportsImages.cs ├── Properties │ ├── Resources.Designer.cs │ ├── Resources.resx │ └── launchSettings.json ├── SchedulesDirect.cs ├── Services │ ├── DescriptionService.cs │ ├── LineupService.cs │ ├── ProgramRepository.cs │ ├── ProgramService.cs │ └── ScheduleService.cs └── StreamMaster.SchedulesDirect.csproj ├── StreamMaster.Streams.Domain ├── Args │ └── ProcessExitEventArgs.cs ├── CacheManager.cs ├── Events │ ├── SourceBroadcasterStopped.cs │ └── StreamTimedOut.cs ├── Exceptions │ └── SourceBroadcasterNotFoundException.cs ├── GlobalUsings.cs ├── Helpers │ ├── ChannelHelper.cs │ └── FileSaver.cs ├── Interfaces │ ├── ICacheManager.cs │ ├── IChannelBroadcaster.cs │ ├── IChannelBroadcasterService.cs │ ├── IChannelLockService.cs │ ├── IChannelService.cs │ ├── IClientConfiguration.cs │ ├── IClientConfigurationService.cs │ ├── ICommandExecutor.cs │ ├── ICommandStream.cs │ ├── ICustomPlayListStream.cs │ ├── IDubcer.cs │ ├── IHTTPStream.cs │ ├── IIntroStatus.cs │ ├── IMultiViewPlayListStream.cs │ ├── ISMStream.cs │ ├── ISourceBroadcaster.cs │ ├── ISourceBroadcasterService.cs │ ├── ISourceName.cs │ ├── IStreamConnectionService.cs │ ├── IStreamDataToClients.cs │ ├── IStreamFactory.cs │ ├── IStreamHandlerMetrics.cs │ ├── IStreamLimitsService.cs │ ├── IStreamMetricsRecorder.cs │ ├── IStreamStats.cs │ ├── IStreamStatus.cs │ ├── ISwitchToNextStreamService.cs │ ├── IVideoCombiner.cs │ ├── IVideoCombinerService.cs │ ├── IVideoInfoService.cs │ ├── IVideoService.cs │ ├── StreamResult.cs │ └── StreamingClientInformation.cs ├── Metrics │ ├── BPSMetrics.cs │ ├── StreamConnectionMetric.cs │ ├── StreamConnectionMetricManager.cs │ ├── StreamConnectionMetricSerializer.cs │ ├── StreamConnectionService.cs │ └── StreamHandlerMetrics.cs ├── Models │ ├── ChannelMetric.cs │ ├── ClientChannelDto.cs │ ├── ClientStreamsDto.cs │ ├── GetStreamResult.cs │ └── ProxyStreamError.cs └── StreamMaster.Streams.Domain.csproj ├── StreamMaster.Streams ├── Broadcasters │ ├── ChannelBroadcaster.cs │ ├── ChannelBroadcasterService.cs │ ├── SourceBroadcaster.cs │ └── SourceBroadcasterService.cs ├── Channels │ └── ChannelService.cs ├── ClientConfiguration.cs ├── ConfigureServices.cs ├── Factories │ ├── CommandExecutor.cs │ └── StreamFactory.cs ├── GlobalUsings.cs ├── Plugins │ ├── CircularBuffer.cs │ ├── VideoInfoEventArgs.cs │ ├── VideoInfoPlugin.cs │ └── VideoInfoService.cs ├── Services │ ├── ChannelLockService.cs │ ├── ClientConfigurationService.cs │ ├── Dubcer.cs │ ├── StreamLimitsService.cs │ ├── StreamMetricsRecorder.cs │ ├── SwitchToNextStreamService.cs │ └── VideoService.cs ├── StreamMaster.Streams.csproj └── Streams │ ├── CommandStream.cs │ ├── CustomPlayListStream.cs │ ├── HTTPStream.cs │ └── MultiViewPlayListStream.cs ├── StreamMaster.WebUI ├── .all-contributorsrc ├── .dockerignore ├── .eslintrc.json ├── .estlintignore ├── .gitignore ├── .hintrc ├── .prettierignore ├── .prettierrc.json ├── .vscode │ ├── extensions.json │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── StreamMaster.WebUI.esproj ├── app │ ├── App.tsx │ ├── RequireAuth.tsx │ ├── RootLayout.tsx │ ├── RootSideBar.tsx │ ├── Router.tsx │ ├── editor │ │ ├── files │ │ │ └── page.tsx │ │ ├── playlist │ │ │ └── page.tsx │ │ ├── sd │ │ │ └── page.tsx │ │ ├── streamgroup │ │ │ └── page.tsx │ │ └── streams │ │ │ └── page.tsx │ ├── index.tsx │ ├── login │ │ └── Login.tsx │ ├── settings │ │ └── page.tsx │ ├── streamingstatus │ │ └── page.tsx │ ├── testing │ │ └── page.tsx │ └── viewer │ │ ├── logviewer │ │ └── page.tsx │ │ └── player │ │ └── page.tsx ├── biome.json ├── build_theme.js ├── components │ ├── AnimatedText.tsx │ ├── ChannelHandlerSelector.tsx │ ├── ChannelNameEditor.tsx │ ├── ChannelNumberEditor.tsx │ ├── MenuItemSM.tsx │ ├── StandardHeader.tsx │ ├── buttons │ │ ├── AddButton.tsx │ │ ├── AutoSetButton.tsx │ │ ├── BanButton.tsx │ │ ├── BookButton.tsx │ │ ├── ChildButtonProperties.ts │ │ ├── ClearButton.tsx │ │ ├── ClockButton.tsx │ │ ├── CloseButton.tsx │ │ ├── CopyButton.tsx │ │ ├── DownArrowButton.tsx │ │ ├── EditButton.tsx │ │ ├── GoButton.tsx │ │ ├── ImageButton.tsx │ │ ├── LeftArrowButton.tsx │ │ ├── LinkButton.tsx │ │ ├── MaximizeButton.tsx │ │ ├── MinusButton.tsx │ │ ├── OKButton.tsx │ │ ├── RefreshButton.tsx │ │ ├── ResetButton.tsx │ │ ├── RightArrowButton.tsx │ │ ├── SGAddButton.tsx │ │ ├── SGRemoveButton.tsx │ │ ├── SaveButton.tsx │ │ ├── SearchButton.tsx │ │ ├── SimpleButton.tsx │ │ ├── SunButton.tsx │ │ ├── UploadButton.tsx │ │ ├── VisibleButton.tsx │ │ └── XButton.tsx │ ├── channelGroups │ │ ├── BaseChannelGroupPagedSelector.tsx │ │ ├── BaseChannelGroupSelector.tsx │ │ ├── ChannelGroupAddDialog.tsx │ │ ├── ChannelGroupDeleteDialog.tsx │ │ ├── ChannelGroupNameEditor.tsx │ │ ├── ChannelGroupSelector.tsx │ │ ├── ChannelGroupSelectorForSMChannels.tsx │ │ └── ChannelGroupVisibleDialog.tsx │ ├── columns │ │ ├── ChannelGroups │ │ │ ├── createChannelGroupMultiSelectColumnConfigHook.tsx │ │ │ └── useChannelGroupNameColumnConfig.tsx │ │ ├── createMultiSelectLineUpColumnConfigHook.tsx │ │ ├── useChannelNameColumnConfig.tsx │ │ ├── useChannelNumberColumnConfig.tsx │ │ ├── useEPGColumnConfig.tsx │ │ ├── useLineUpColumnConfig.tsx │ │ ├── useM3UFileNameColumnConfig.tsx │ │ ├── useM3UFilesMaxStreamsColumnConfig.tsx │ │ └── useVideoStreamLogoColumnConfig.tsx │ ├── customPlayList │ │ └── SyncCustomListsButton.tsx │ ├── epg │ │ ├── EPGEditor.tsx │ │ └── EPGSelector.tsx │ ├── epgFiles │ │ ├── EPGFileCreateDialog.tsx │ │ ├── EPGFileDeleteDialog.tsx │ │ ├── EPGFileDialog.tsx │ │ ├── EPGFileEditDialog.tsx │ │ ├── EPGFileRefreshDialog.tsx │ │ ├── EPGFilesButton.tsx │ │ ├── EPGFilesDataSelector.tsx │ │ ├── EPGFilesEditor.tsx │ │ └── EPGPreviewDialog.tsx │ ├── export │ │ └── ExportButton.tsx │ ├── file │ │ ├── FileRefreshDialog.tsx │ │ ├── FileRemoveDialog.tsx │ │ └── useFileUpload.tsx │ ├── icons │ │ ├── CustomLogosAddDialog.tsx │ │ ├── CustomLogosDataSelector.tsx │ │ ├── CustomLogosDialog.tsx │ │ ├── IconSelector.tsx │ │ └── iconUtil.ts │ ├── inputs │ │ ├── BooleanEditor.tsx │ │ ├── ColorEditor.tsx │ │ ├── DropDownEditorBodyTemplate.tsx │ │ ├── NumberEditor.tsx │ │ ├── PasswordEditor.tsx │ │ ├── PopUpStringEditor.tsx │ │ ├── SMChannelGroupDropDown.tsx │ │ ├── StringEditor.tsx │ │ ├── StringTracker.tsx │ │ └── TextInput.tsx │ ├── loader │ │ ├── SMLoader.tsx │ │ ├── ball-beat.css │ │ ├── ball-fussion.css │ │ ├── ball-grid-beat.css │ │ ├── ball-newton-cradle.css │ │ └── ball-spin-clockwise-fade.css │ ├── m3u │ │ ├── DialogTemplates │ │ │ └── DialogchooseOptions.tsx │ │ ├── M3UFieldNameDialog.tsx │ │ ├── M3UFileCreateDialog.tsx │ │ ├── M3UFileDeleteDialog.tsx │ │ ├── M3UFileDialog.tsx │ │ ├── M3UFileEditDialog.tsx │ │ ├── M3UFileRefreshDialog.tsx │ │ ├── M3UFileTags.tsx │ │ ├── M3UFileTagsDialog.tsx │ │ ├── M3UFilesButton.tsx │ │ ├── M3UFilesDataSelector.tsx │ │ ├── M3UFilesMaxStreamsEditor.tsx │ │ ├── M3UKeyDialog.tsx │ │ └── StreamURLPrefixSelector.tsx │ ├── profiles │ │ ├── AttachStreamGroupProfileDialog.tsx │ │ ├── CommandProfileDataSelector.tsx │ │ ├── CommandProfileDropDown.tsx │ │ ├── CreateCommandProfileDialog.tsx │ │ ├── CreateOutputProfileDialog.tsx │ │ ├── OutputProfileDataSelector.tsx │ │ ├── OutputProfileDropDown.tsx │ │ ├── RemoveCommandProfileDialog.tsx │ │ ├── RemoveOutputProfileDialog.tsx │ │ ├── RemoveStreamGroupProfileDialog.tsx │ │ ├── StreamGroupProfileButton.tsx │ │ └── columns │ │ │ ├── OutputProfileValueDropDown.tsx │ │ │ ├── useCommandProfileColumnConfig.tsx │ │ │ ├── useCommandProfileCommandColumnConfig.tsx │ │ │ ├── useCommandProfileParametersColumnConfig.tsx │ │ │ ├── useOutputProfileChannelIdColumnConfig.tsx │ │ │ ├── useOutputProfileChannelNumberColumnConfig.tsx │ │ │ ├── useOutputProfileColumnConfig.tsx │ │ │ ├── useOutputProfileEPGIdColumnConfig.tsx │ │ │ ├── useOutputProfileGroupColumnConfig.tsx │ │ │ ├── useOutputProfileGroupTitleColumnConfig.tsx │ │ │ ├── useOutputProfileIconColumnConfig.tsx │ │ │ ├── useOutputProfileIdColumnConfig.tsx │ │ │ ├── useOutputProfileNameColumnConfig.tsx │ │ │ ├── useStreamGroupProfileColumnConfig.tsx │ │ │ └── useStreamGroupProfileFileProfileColumnConfig.tsx │ ├── schedulesDirect │ │ ├── SchedulesDirectAddHeadendDialog.tsx │ │ ├── SchedulesDirectCountrySelector.tsx │ │ ├── SchedulesDirectHeadendDataSelector.tsx │ │ ├── SchedulesDirectLineUpsDataSelector.tsx │ │ ├── SchedulesDirectLineupPreviewChannel.tsx │ │ ├── SchedulesDirectRemoveHeadendDialog.tsx │ │ └── SchedulesDirectStationDataSelector.tsx │ ├── selectors │ │ └── TriSelectShowSelection.tsx │ ├── settings │ │ ├── SettingsNameRegexAddDialog.tsx │ │ ├── SettingsNameRegexDataSelector.tsx │ │ └── SettingsNameRegexDeleteDialog.tsx │ ├── sm │ │ ├── Interfaces │ │ │ ├── SMButtonProperties.ts │ │ │ ├── SMCardProperties.ts │ │ │ ├── SMDropDownProperties.ts │ │ │ ├── SMModalProperties.ts │ │ │ ├── SMOverlayProperties.ts │ │ │ ├── SMPopUpProperties.ts │ │ │ ├── SMProperties.ts │ │ │ ├── SMScrollerProperties.ts │ │ │ ├── SMSpeedDialTypes.ts │ │ │ └── SourceOrFileDialogProperties.ts │ │ ├── SMButton.tsx │ │ ├── SMCard.tsx │ │ ├── SMDialog.tsx │ │ ├── SMDropDown.tsx │ │ ├── SMFileUpload.tsx │ │ ├── SMOverlay.tsx │ │ ├── SMPopUp.tsx │ │ ├── SMScroller.tsx │ │ ├── SMSpeedMenu.tsx │ │ ├── SMSpeedMenuItem.tsx │ │ ├── SMTextColor.tsx │ │ ├── SMTextDefaults.tsx │ │ ├── SMTriSelectShowHidden.tsx │ │ ├── SMTriSelectShowSG.tsx │ │ ├── SMTriSelectShowSelect.tsx │ │ ├── SMTriSelectShowSelected.tsx │ │ ├── SourceOrFileDialog.tsx │ │ ├── helpers │ │ │ ├── calculateBackgroundStyle.ts │ │ │ └── calculateChildPosition.ts │ │ └── hooks │ │ │ └── useClickOutside.ts │ ├── smDataTable │ │ ├── SMDataTable.tsx │ │ ├── SMDataTableSkeleton.tsx │ │ ├── helpers │ │ │ ├── TableHeader.tsx │ │ │ ├── arraysEqual.ts │ │ │ ├── bodyTemplate.tsx │ │ │ ├── dataSelectorFunctions.ts │ │ │ ├── generateFilterData.tsx │ │ │ ├── getColumnClassNames.ts │ │ │ ├── getColumnStyles.ts │ │ │ ├── getEmptyFilter.ts │ │ │ ├── getHeader.tsx │ │ │ ├── getRecord.ts │ │ │ ├── getRecordString.tsx │ │ │ └── isPagedResponse.ts │ │ ├── hooks │ │ │ ├── epgLinkTemplate.tsx │ │ │ ├── m3uLinkTemplate.tsx │ │ │ ├── urlTemplate.tsx │ │ │ ├── useSMDataTableState.tsx │ │ │ └── useSetQueryFilter.tsx │ │ ├── templates │ │ │ ├── blankTemplate.tsx │ │ │ ├── defaultTemplate.tsx │ │ │ ├── epgSourceTemplate.tsx │ │ │ ├── imageBodyTemplate.tsx │ │ │ ├── isHiddenTemplate.tsx │ │ │ └── streamsBodyTemplate.tsx │ │ └── types │ │ │ ├── ColumnMeta.ts │ │ │ ├── smDataTableInterfaces.ts │ │ │ └── smDataTableTypes.ts │ ├── smchannels │ │ ├── AddSMChannelsToGroupEditor.tsx │ │ ├── AddSMChannelsToSGEditor.tsx │ │ ├── AutoSetEPGSMChannelButton.tsx │ │ ├── AutoSetEPGSMChannelDialog.tsx │ │ ├── AutoSetSMChannelNumbersDialog.tsx │ │ ├── CloneSMChannelDialog.tsx │ │ ├── CommandProfileNameSelector.tsx │ │ ├── CreateMultiViewSMChannelDialog.tsx │ │ ├── CreateSMChannelDialog.tsx │ │ ├── CreateSMChannelsFromSMStreamsDialog.tsx │ │ ├── DeleteSMChannelDialog.tsx │ │ ├── DeleteSMChannelsDialog.tsx │ │ ├── EditSMChannelDialog.tsx │ │ ├── SMChannelDataForSMChannelSelector.tsx │ │ ├── SMChannelDataForSMChannelSelectorForDataKey.tsx │ │ ├── SMChannelDialog.tsx │ │ ├── SMChannelLogoEditor.tsx │ │ ├── SMChannelMultiVisibleDialog.tsx │ │ ├── SMChannelNameEditor.tsx │ │ ├── SMChannelNumberEditor.tsx │ │ ├── SMChannelSMChannelDataSelector.tsx │ │ ├── SMChannelSMChannelDataSelectorForDataKey.tsx │ │ ├── SMChannelSMChannelDialog.tsx │ │ ├── SMChannelSMChannelFromDataKeyDialog.tsx │ │ ├── SMChannelSMStreamDataSelector.tsx │ │ ├── SMChannelSMStreamDataSelectorForDataKey.tsx │ │ ├── SMChannelSMStreamDialog.tsx │ │ ├── SMChannelSMStreamFromDataKeyDialog.tsx │ │ ├── SMMultiViewChannelDialog.tsx │ │ ├── SMStreamDataForSMChannelSelector.tsx │ │ ├── SMStreamDataForSMChannelSelectorForDataKey.tsx │ │ ├── SetSMChannelsCommandProfileNameDialog.tsx │ │ ├── SetSMChannelsLogoFromEPGDialog.tsx │ │ └── columns │ │ │ ├── SMChannelGroupEditor.tsx │ │ │ ├── SMChannelSGEditor.tsx │ │ │ ├── createSMChannelMultiSelectColumnConfigHook.tsx │ │ │ ├── useSMChannelEPGColumnConfig.tsx │ │ │ ├── useSMChannelGroupColumnConfig.tsx │ │ │ ├── useSMChannelLogoColumnConfig.tsx │ │ │ ├── useSMChannelNameColumnConfig.tsx │ │ │ ├── useSMChannelNumberColumnConfig.tsx │ │ │ ├── useSMChannelSGColumnConfig.tsx │ │ │ └── useSMVideoOutputProfileNameColumnConfig.tsx │ ├── smstreams │ │ ├── CreateSMStreamDialog.tsx │ │ ├── DeleteSMStreamDialog.tsx │ │ ├── EditSMStreamDialog.tsx │ │ ├── PlaySMStreamDialog.tsx │ │ ├── SMStreamDialog.tsx │ │ ├── StreamCopyLinkDialog.tsx │ │ ├── StreamMultiVisibleDialog.tsx │ │ ├── StreamVisibleDialog.tsx │ │ └── columns │ │ │ ├── useSMStreamChannelGroupColumnConfig.tsx │ │ │ ├── useSMStreamM3UColumnConfig.tsx │ │ │ └── useSMStreamMembershipColumnConfig.tsx │ ├── smtasks │ │ ├── SMTasksButton.tsx │ │ └── SMTasksDataSelector.tsx │ ├── streamGroup │ │ ├── StreamGroupButton.tsx │ │ ├── StreamGroupCreateDialog.tsx │ │ ├── StreamGroupDataSelector.tsx │ │ ├── StreamGroupDataSelectorValue.tsx │ │ ├── StreamGroupDeleteDialog.tsx │ │ ├── StreamGroupSelector.tsx │ │ └── columns │ │ │ ├── useStreamGroupAutoSetChannelNumbersColumnConfig.tsx │ │ │ ├── useStreamGroupDeviceIDColumnConfig.tsx │ │ │ ├── useStreamGroupIgnoreExistingChannelNumbersColumnConfig.tsx │ │ │ └── useStreamGroupStartChnColumnConfig.tsx │ ├── streaming │ │ ├── CancelChannelDialog.tsx │ │ ├── CancelClientDialog.tsx │ │ └── MoveToNextStreamDialog.tsx │ └── vs │ │ ├── VButton.tsx │ │ └── VDataSelector.tsx ├── features │ ├── logViewer │ │ └── LogViewer.tsx │ ├── sdEditor │ │ ├── SDEditor.tsx │ │ └── SDEditorChannels.tsx │ ├── settings │ │ ├── About.tsx │ │ ├── AuthenticationSettings.tsx │ │ ├── BackupSettings.tsx │ │ ├── BaseSettings.tsx │ │ ├── DevelopmentSettings.tsx │ │ ├── GeneralSettings.tsx │ │ ├── LogDisplay.tsx │ │ ├── LogsDialog.tsx │ │ ├── MiscSettings.tsx │ │ ├── SDSettings.tsx │ │ ├── SecuritySettings.tsx │ │ ├── SettingsEditor.tsx │ │ ├── SettingsInterface.ts │ │ ├── SettingsUtils.tsx │ │ ├── SpeedMenuTest.tsx │ │ ├── StreamingSettings.tsx │ │ └── components │ │ │ ├── GetCheckBoxLine.tsx │ │ │ ├── GetDropDownLine.tsx │ │ │ ├── GetInputNumberLine.tsx │ │ │ ├── GetInputTextLine.tsx │ │ │ ├── GetLine.tsx │ │ │ └── GetPasswordLine.tsx │ ├── streameditor │ │ ├── SMChannelDataSelector.tsx │ │ ├── SMChannelDataSelectorValue.tsx │ │ ├── SMChannelMenu.tsx │ │ ├── SMStreamDataSelector.tsx │ │ ├── SMStreamDataSelectorValue.tsx │ │ ├── SMStreamMenu.tsx │ │ ├── StreamEditor.tsx │ │ └── useSelectedSMItems.tsx │ └── streamingStatus │ │ ├── DownloadStatusDataSelector.tsx │ │ ├── DownloadStatusView.tsx │ │ ├── SMChannelStatus.tsx │ │ ├── SMChannelStatusValue.tsx │ │ ├── SMClientStatus.tsx │ │ ├── SMStatistics.tsx │ │ ├── SMStreamingStatus.tsx │ │ ├── StreamInfoDisplay.tsx │ │ ├── StreamingStatus.tsx │ │ └── VideoInfoDisplay.tsx ├── index.html ├── lib │ ├── Cache │ │ ├── cacheUtils.ts │ │ ├── useStorageCache.ts │ │ └── utils │ │ │ ├── clearCacheItem.ts │ │ │ ├── getCacheItem.ts │ │ │ ├── removeCacheItem.ts │ │ │ ├── setCacheField.ts │ │ │ └── setCacheItem.ts │ ├── FileUploadService.tsx │ ├── apiDefs.ts │ ├── axios.ts │ ├── common │ │ ├── SDLogoIcon.tsx │ │ ├── colors.ts │ │ ├── common.tsx │ │ ├── crypto.ts │ │ ├── dataTypes.ts │ │ ├── dateTime.ts │ │ ├── enumTools.ts │ │ ├── getParameters.ts │ │ ├── icons.tsx │ │ ├── intl.tsx │ │ ├── isSkipToken.ts │ │ ├── logger.ts │ │ ├── propertyExists.ts │ │ └── stringUtils.ts │ ├── context │ │ ├── SMProvider.tsx │ │ └── SettingsProvider.tsx │ ├── contributors.js │ ├── hooks │ │ ├── eventManager.ts │ │ ├── useCopyToClipboard.tsx │ │ ├── useElementSize.tsx │ │ ├── useScrollAndKeyEvents.tsx │ │ ├── useSelectedAndQ.tsx │ │ └── useWindowSize.tsx │ ├── i18n │ │ ├── config.ts │ │ └── en │ │ │ └── translation.json │ ├── locales │ │ ├── MessagesEn.tsx │ │ ├── default_setting.tsx │ │ └── help_en.tsx │ ├── redux │ │ ├── emptyApi.ts │ │ ├── hooks.ts │ │ ├── hooks │ │ │ ├── currentSettingRequest.ts │ │ │ ├── filters.ts │ │ │ ├── isTrue.ts │ │ │ ├── loading.ts │ │ │ ├── messages.ts │ │ │ ├── queryAdditionalFilters.ts │ │ │ ├── queryFilter.ts │ │ │ ├── selectAll.ts │ │ │ ├── selectedCountry.ts │ │ │ ├── selectedItems.ts │ │ │ ├── selectedPostalCode.ts │ │ │ ├── selectedSMChannel.ts │ │ │ ├── selectedSMStream.ts │ │ │ ├── selectedSMStreams.ts │ │ │ ├── selectedStreamGroup.ts │ │ │ ├── showHidden.ts │ │ │ ├── showSelected.ts │ │ │ ├── showSelections.ts │ │ │ ├── sortInfo.ts │ │ │ ├── stringValue.ts │ │ │ ├── updateSettingRequest.ts │ │ │ ├── useAnyEntity.ts │ │ │ ├── useEntityStorage.ts │ │ │ ├── useIsCellLoading.ts │ │ │ ├── useIsRowLoading.ts │ │ │ └── useSMMessages.ts │ │ ├── reducers.ts │ │ ├── store.ts │ │ ├── updateFieldInData.ts │ │ └── updatePagedResponseFieldInData.ts │ ├── settings.ts │ ├── signalr │ │ ├── MessageProcessor.tsx │ │ ├── SignalRAuthLogOut.tsx │ │ ├── SignalRProvider.tsx │ │ └── SignalRService.ts │ ├── smAPI │ │ ├── ChannelGroups │ │ │ ├── ChannelGroupsCommands.ts │ │ │ ├── GetChannelGroupsFetch.ts │ │ │ ├── GetChannelGroupsFromSMChannelsFetch.ts │ │ │ ├── GetChannelGroupsFromSMChannelsSlice.ts │ │ │ ├── GetChannelGroupsSlice.ts │ │ │ ├── GetPagedChannelGroupsFetch.ts │ │ │ ├── GetPagedChannelGroupsSlice.ts │ │ │ ├── useGetChannelGroups.tsx │ │ │ ├── useGetChannelGroupsFromSMChannels.tsx │ │ │ └── useGetPagedChannelGroups.tsx │ │ ├── Custom │ │ │ ├── CustomCommands.ts │ │ │ ├── GetCustomPlayListFetch.ts │ │ │ ├── GetCustomPlayListSlice.ts │ │ │ ├── GetCustomPlayListsFetch.ts │ │ │ ├── GetCustomPlayListsSlice.ts │ │ │ ├── GetIntroPlayListsFetch.ts │ │ │ ├── GetIntroPlayListsSlice.ts │ │ │ ├── useGetCustomPlayList.tsx │ │ │ ├── useGetCustomPlayLists.tsx │ │ │ └── useGetIntroPlayLists.tsx │ │ ├── DataRefreshAll.ts │ │ ├── EPG │ │ │ ├── EPGCommands.ts │ │ │ ├── GetEPGColorsFetch.ts │ │ │ ├── GetEPGColorsSlice.ts │ │ │ └── useGetEPGColors.tsx │ │ ├── EPGFiles │ │ │ ├── EPGFilesCommands.ts │ │ │ ├── GetEPGFileNamesFetch.ts │ │ │ ├── GetEPGFileNamesSlice.ts │ │ │ ├── GetEPGFilePreviewByIdFetch.ts │ │ │ ├── GetEPGFilePreviewByIdSlice.ts │ │ │ ├── GetEPGFilesFetch.ts │ │ │ ├── GetEPGFilesSlice.ts │ │ │ ├── GetEPGNextEPGNumberFetch.ts │ │ │ ├── GetEPGNextEPGNumberSlice.ts │ │ │ ├── GetPagedEPGFilesFetch.ts │ │ │ ├── GetPagedEPGFilesSlice.ts │ │ │ ├── useGetEPGFileNames.tsx │ │ │ ├── useGetEPGFilePreviewById.tsx │ │ │ ├── useGetEPGFiles.tsx │ │ │ ├── useGetEPGNextEPGNumber.tsx │ │ │ └── useGetPagedEPGFiles.tsx │ │ ├── General │ │ │ └── GeneralCommands.ts │ │ ├── Logos │ │ │ ├── GetCustomLogosFetch.ts │ │ │ ├── GetCustomLogosSlice.ts │ │ │ ├── GetLogoFetch.ts │ │ │ ├── GetLogoForChannelFetch.ts │ │ │ ├── GetLogoForChannelSlice.ts │ │ │ ├── GetLogoSlice.ts │ │ │ ├── GetLogosFetch.ts │ │ │ ├── GetLogosSlice.ts │ │ │ ├── LogosCommands.ts │ │ │ ├── useGetCustomLogos.tsx │ │ │ ├── useGetLogo.tsx │ │ │ ├── useGetLogoForChannel.tsx │ │ │ └── useGetLogos.tsx │ │ ├── Logs │ │ │ ├── GetLogContentsFetch.ts │ │ │ ├── GetLogContentsSlice.ts │ │ │ ├── GetLogNamesFetch.ts │ │ │ ├── GetLogNamesSlice.ts │ │ │ ├── LogsCommands.ts │ │ │ ├── useGetLogContents.tsx │ │ │ └── useGetLogNames.tsx │ │ ├── M3UFiles │ │ │ ├── GetM3UFileNamesFetch.ts │ │ │ ├── GetM3UFileNamesSlice.ts │ │ │ ├── GetM3UFilesFetch.ts │ │ │ ├── GetM3UFilesSlice.ts │ │ │ ├── GetPagedM3UFilesFetch.ts │ │ │ ├── GetPagedM3UFilesSlice.ts │ │ │ ├── M3UFilesCommands.ts │ │ │ ├── useGetM3UFileNames.tsx │ │ │ ├── useGetM3UFiles.tsx │ │ │ └── useGetPagedM3UFiles.tsx │ │ ├── Profiles │ │ │ ├── GetCommandProfilesFetch.ts │ │ │ ├── GetCommandProfilesSlice.ts │ │ │ ├── GetOutputProfileFetch.ts │ │ │ ├── GetOutputProfileSlice.ts │ │ │ ├── GetOutputProfilesFetch.ts │ │ │ ├── GetOutputProfilesSlice.ts │ │ │ ├── ProfilesCommands.ts │ │ │ ├── useGetCommandProfiles.tsx │ │ │ ├── useGetOutputProfile.tsx │ │ │ └── useGetOutputProfiles.tsx │ │ ├── SMChannelChannelLinks │ │ │ ├── GetSMChannelChannelsFetch.ts │ │ │ ├── GetSMChannelChannelsSlice.ts │ │ │ ├── SMChannelChannelLinksCommands.ts │ │ │ └── useGetSMChannelChannels.tsx │ │ ├── SMChannelStreamLinks │ │ │ ├── GetSMChannelStreamsFetch.ts │ │ │ ├── GetSMChannelStreamsSlice.ts │ │ │ ├── SMChannelStreamLinksCommands.ts │ │ │ └── useGetSMChannelStreams.tsx │ │ ├── SMChannels │ │ │ ├── GetPagedSMChannelsFetch.ts │ │ │ ├── GetPagedSMChannelsSlice.ts │ │ │ ├── GetSMChannelUniqueNameFetch.ts │ │ │ ├── GetSMChannelUniqueNameSlice.ts │ │ │ ├── SMChannelsCommands.ts │ │ │ ├── useGetPagedSMChannels.tsx │ │ │ └── useGetSMChannelUniqueName.tsx │ │ ├── SMMessages │ │ │ └── SMMessagesCommands.ts │ │ ├── SMStreams │ │ │ ├── GetPagedSMStreamsFetch.ts │ │ │ ├── GetPagedSMStreamsSlice.ts │ │ │ ├── SMStreamsCommands.ts │ │ │ └── useGetPagedSMStreams.tsx │ │ ├── SMTasks │ │ │ ├── GetSMTasksFetch.ts │ │ │ ├── GetSMTasksSlice.ts │ │ │ ├── SMTasksCommands.ts │ │ │ └── useGetSMTasks.tsx │ │ ├── SchedulesDirect │ │ │ ├── GetAvailableCountriesFetch.ts │ │ │ ├── GetAvailableCountriesSlice.ts │ │ │ ├── GetHeadendsByCountryPostalFetch.ts │ │ │ ├── GetHeadendsByCountryPostalSlice.ts │ │ │ ├── GetHeadendsToViewFetch.ts │ │ │ ├── GetHeadendsToViewSlice.ts │ │ │ ├── GetLineupPreviewChannelFetch.ts │ │ │ ├── GetLineupPreviewChannelSlice.ts │ │ │ ├── GetSelectedStationIdsFetch.ts │ │ │ ├── GetSelectedStationIdsSlice.ts │ │ │ ├── GetStationChannelNamesFetch.ts │ │ │ ├── GetStationChannelNamesSlice.ts │ │ │ ├── GetStationPreviewsFetch.ts │ │ │ ├── GetStationPreviewsSlice.ts │ │ │ ├── GetSubScribedHeadendsFetch.ts │ │ │ ├── GetSubScribedHeadendsSlice.ts │ │ │ ├── GetSubscribedLineupsFetch.ts │ │ │ ├── GetSubscribedLineupsSlice.ts │ │ │ ├── SchedulesDirectCommands.ts │ │ │ ├── useGetAvailableCountries.tsx │ │ │ ├── useGetHeadendsByCountryPostal.tsx │ │ │ ├── useGetHeadendsToView.tsx │ │ │ ├── useGetLineupPreviewChannel.tsx │ │ │ ├── useGetSelectedStationIds.tsx │ │ │ ├── useGetStationChannelNames.tsx │ │ │ ├── useGetStationPreviews.tsx │ │ │ ├── useGetSubScribedHeadends.tsx │ │ │ └── useGetSubscribedLineups.tsx │ │ ├── Settings │ │ │ ├── GetSettingsFetch.ts │ │ │ ├── GetSettingsSlice.ts │ │ │ ├── SettingsCommands.ts │ │ │ └── useGetSettings.tsx │ │ ├── Statistics │ │ │ ├── GetChannelMetricsFetch.ts │ │ │ ├── GetChannelMetricsSlice.ts │ │ │ ├── GetDownloadServiceStatusFetch.ts │ │ │ ├── GetDownloadServiceStatusSlice.ts │ │ │ ├── GetIsSystemReadyFetch.ts │ │ │ ├── GetIsSystemReadySlice.ts │ │ │ ├── GetStreamConnectionMetricDataFetch.ts │ │ │ ├── GetStreamConnectionMetricDataSlice.ts │ │ │ ├── GetStreamConnectionMetricDatasFetch.ts │ │ │ ├── GetStreamConnectionMetricDatasSlice.ts │ │ │ ├── GetSystemStatusFetch.ts │ │ │ ├── GetSystemStatusSlice.ts │ │ │ ├── GetTaskIsRunningFetch.ts │ │ │ ├── GetTaskIsRunningSlice.ts │ │ │ ├── GetVideoInfoFetch.ts │ │ │ ├── GetVideoInfoSlice.ts │ │ │ ├── GetVideoInfosFetch.ts │ │ │ ├── GetVideoInfosSlice.ts │ │ │ ├── StatisticsCommands.ts │ │ │ ├── useGetChannelMetrics.tsx │ │ │ ├── useGetDownloadServiceStatus.tsx │ │ │ ├── useGetIsSystemReady.tsx │ │ │ ├── useGetStreamConnectionMetricData.tsx │ │ │ ├── useGetStreamConnectionMetricDatas.tsx │ │ │ ├── useGetSystemStatus.tsx │ │ │ ├── useGetTaskIsRunning.tsx │ │ │ ├── useGetVideoInfo.tsx │ │ │ └── useGetVideoInfos.tsx │ │ ├── StreamGroupSMChannelLinks │ │ │ ├── GetStreamGroupSMChannelsFetch.ts │ │ │ ├── GetStreamGroupSMChannelsSlice.ts │ │ │ ├── StreamGroupSMChannelLinksCommands.ts │ │ │ └── useGetStreamGroupSMChannels.tsx │ │ ├── StreamGroups │ │ │ ├── GetPagedStreamGroupsFetch.ts │ │ │ ├── GetPagedStreamGroupsSlice.ts │ │ │ ├── GetStreamGroupFetch.ts │ │ │ ├── GetStreamGroupProfilesFetch.ts │ │ │ ├── GetStreamGroupProfilesSlice.ts │ │ │ ├── GetStreamGroupSlice.ts │ │ │ ├── GetStreamGroupsFetch.ts │ │ │ ├── GetStreamGroupsSlice.ts │ │ │ ├── StreamGroupsCommands.ts │ │ │ ├── useGetPagedStreamGroups.tsx │ │ │ ├── useGetStreamGroup.tsx │ │ │ ├── useGetStreamGroupProfiles.tsx │ │ │ └── useGetStreamGroups.tsx │ │ ├── Streaming │ │ │ └── StreamingCommands.ts │ │ ├── Vs │ │ │ ├── GetVsFetch.ts │ │ │ ├── GetVsSlice.ts │ │ │ ├── VsCommands.ts │ │ │ └── useGetVs.tsx │ │ ├── WebSocket │ │ │ └── WebSocketCommands.ts │ │ └── smapiTypes.ts │ └── styles │ │ ├── dataSelector.css │ │ ├── index.css │ │ ├── streammaster-dark.css │ │ └── streammaster-light.css ├── package.json ├── public │ ├── Content │ │ ├── Fonts │ │ │ ├── Roboto-Light.ttf │ │ │ ├── Roboto-Light.woff │ │ │ ├── Roboto-Light.woff2 │ │ │ ├── Roboto-Regular.ttf │ │ │ ├── Roboto-Regular.woff │ │ │ ├── Roboto-Regular.woff2 │ │ │ ├── UbuntuMono-Regular.eot │ │ │ ├── UbuntuMono-Regular.ttf │ │ │ ├── UbuntuMono-Regular.woff │ │ │ ├── fonts.css │ │ │ ├── text-security-disc.ttf │ │ │ └── text-security-disc.woff │ │ ├── StreamMasterx32.png │ │ └── styles.css │ ├── StreamMasterx32.png │ ├── config.json │ ├── favicon.ico │ ├── images │ │ ├── default.png │ │ ├── mrmonday_logo_sm.png │ │ ├── senex_logo_sm.png │ │ ├── streammaster_logo.png │ │ ├── streammaster_logo_small.png │ │ └── transparent.png │ ├── index.html │ ├── login.html │ ├── manifest.json │ ├── robots.txt │ └── themes │ │ ├── streammaster-dark │ │ ├── fonts │ │ │ ├── poppins-v15-latin-ext_latin-300.woff │ │ │ ├── poppins-v15-latin-ext_latin-300.woff2 │ │ │ ├── poppins-v15-latin-ext_latin-600.woff │ │ │ ├── poppins-v15-latin-ext_latin-600.woff2 │ │ │ ├── poppins-v15-latin-ext_latin-700.woff │ │ │ ├── poppins-v15-latin-ext_latin-700.woff2 │ │ │ ├── poppins-v15-latin-ext_latin-regular.woff │ │ │ └── poppins-v15-latin-ext_latin-regular.woff2 │ │ └── theme.css │ │ └── streammaster-light │ │ ├── fonts │ │ ├── poppins-v15-latin-ext_latin-300.woff │ │ ├── poppins-v15-latin-ext_latin-300.woff2 │ │ ├── poppins-v15-latin-ext_latin-600.woff │ │ ├── poppins-v15-latin-ext_latin-600.woff2 │ │ ├── poppins-v15-latin-ext_latin-700.woff │ │ ├── poppins-v15-latin-ext_latin-700.woff2 │ │ ├── poppins-v15-latin-ext_latin-regular.woff │ │ └── poppins-v15-latin-ext_latin-regular.woff2 │ │ └── theme.css ├── scripts │ └── parse-contributors.cjs ├── themes │ └── streammaster │ │ ├── _extensions.scss │ │ ├── streammaster-base │ │ ├── _base.scss │ │ ├── _borders.scss │ │ ├── _common.scss │ │ ├── _components.scss │ │ ├── _fonts.scss │ │ ├── _headers.scss │ │ ├── _icons.scss │ │ ├── _index.scss │ │ ├── _sizes.scss │ │ ├── _sm.scss │ │ ├── _standard.scss │ │ ├── _text.scss │ │ ├── _variables.scss │ │ ├── components │ │ │ ├── _list-grid.scss │ │ │ ├── _sm-button.scss │ │ │ ├── _sm-card.scss │ │ │ ├── _sm-channelgroup-selector.scss │ │ │ ├── _sm-col.scss │ │ │ ├── _sm-datatable.scss │ │ │ ├── _sm-dropdown.scss │ │ │ ├── _sm-epg-selector.scss │ │ │ ├── _sm-fileupload.scss │ │ │ ├── _sm-icon-selector.scss │ │ │ ├── _sm-loader.scss │ │ │ ├── _sm-modal.scss │ │ │ ├── _sm-popover.scss │ │ │ ├── _sm-scroller.scss │ │ │ ├── _sm-settings.scss │ │ │ ├── _sm-sourceorfiledialog.scss │ │ │ ├── _sm-streamingproxy-selector.scss │ │ │ ├── _sm_page.scss │ │ │ ├── _sm_scroller.scss │ │ │ ├── _sm_smspeedmenu.scss │ │ │ ├── data │ │ │ │ ├── _datascroller.scss │ │ │ │ ├── _datatable.scss │ │ │ │ ├── _dataview.scss │ │ │ │ ├── _filter.scss │ │ │ │ └── _paginator.scss │ │ │ ├── input │ │ │ │ ├── _dropdown.scss │ │ │ │ ├── _inputnumber.scss │ │ │ │ └── _inputtext.scss │ │ │ └── multimedia │ │ │ │ └── _image.scss │ │ └── fonts │ │ │ ├── poppins-v15-latin-ext_latin-300.woff │ │ │ ├── poppins-v15-latin-ext_latin-300.woff2 │ │ │ ├── poppins-v15-latin-ext_latin-600.woff │ │ │ ├── poppins-v15-latin-ext_latin-600.woff2 │ │ │ ├── poppins-v15-latin-ext_latin-700.woff │ │ │ ├── poppins-v15-latin-ext_latin-700.woff2 │ │ │ ├── poppins-v15-latin-ext_latin-regular.woff │ │ │ └── poppins-v15-latin-ext_latin-regular.woff2 │ │ ├── streammaster-dark.css │ │ ├── streammaster-dark.css.map │ │ ├── streammaster-dark │ │ ├── _variables.scss │ │ └── theme.scss │ │ ├── streammaster-light.css │ │ ├── streammaster-light.css.map │ │ ├── streammaster-light │ │ ├── _variables.scss │ │ ├── old_variables.scss │ │ └── theme.scss │ │ └── theme-base │ │ ├── _colors.scss │ │ ├── _common.scss │ │ ├── _components.scss │ │ ├── _mixins.scss │ │ └── components │ │ ├── button │ │ ├── _button.scss │ │ ├── _speeddial.scss │ │ └── _splitbutton.scss │ │ ├── data │ │ ├── _carousel.scss │ │ ├── _datascroller.scss │ │ ├── _datatable.scss │ │ ├── _dataview.scss │ │ ├── _filter.scss │ │ ├── _orderlist.scss │ │ ├── _organizationchart.scss │ │ ├── _paginator.scss │ │ ├── _picklist.scss │ │ ├── _timeline.scss │ │ ├── _tree.scss │ │ └── _treetable.scss │ │ ├── file │ │ └── _fileupload.scss │ │ ├── input │ │ ├── _autocomplete.scss │ │ ├── _calendar.scss │ │ ├── _cascadeselect.scss │ │ ├── _checkbox.scss │ │ ├── _chips.scss │ │ ├── _colorpicker.scss │ │ ├── _dropdown.scss │ │ ├── _editor.scss │ │ ├── _inputgroup.scss │ │ ├── _inputnumber.scss │ │ ├── _inputswitch.scss │ │ ├── _inputtext.scss │ │ ├── _listbox.scss │ │ ├── _mention.scss │ │ ├── _multiselect.scss │ │ ├── _password.scss │ │ ├── _radiobutton.scss │ │ ├── _rating.scss │ │ ├── _selectbutton.scss │ │ ├── _slider.scss │ │ ├── _togglebutton.scss │ │ ├── _treeselect.scss │ │ └── _tristatecheckbox.scss │ │ ├── menu │ │ ├── _breadcrumb.scss │ │ ├── _contextmenu.scss │ │ ├── _dock.scss │ │ ├── _megamenu.scss │ │ ├── _menu.scss │ │ ├── _menubar.scss │ │ ├── _panelmenu.scss │ │ ├── _slidemenu.scss │ │ ├── _steps.scss │ │ ├── _tabmenu.scss │ │ └── _tieredmenu.scss │ │ ├── messages │ │ ├── _inlinemessage.scss │ │ ├── _message.scss │ │ └── _toast.scss │ │ ├── misc │ │ ├── _avatar.scss │ │ ├── _badge.scss │ │ ├── _blockui.scss │ │ ├── _chip.scss │ │ ├── _inplace.scss │ │ ├── _metergroup.scss │ │ ├── _progressbar.scss │ │ ├── _scrolltop.scss │ │ ├── _skeleton.scss │ │ ├── _tag.scss │ │ └── _terminal.scss │ │ ├── multimedia │ │ ├── _galleria.scss │ │ └── _image.scss │ │ ├── overlay │ │ ├── _confirmpopup.scss │ │ ├── _dialog.scss │ │ ├── _overlaypanel.scss │ │ ├── _sidebar.scss │ │ └── _tooltip.scss │ │ └── panel │ │ ├── _accordion.scss │ │ ├── _card.scss │ │ ├── _divider.scss │ │ ├── _fieldset.scss │ │ ├── _panel.scss │ │ ├── _scrollpanel.scss │ │ ├── _splitter.scss │ │ ├── _tabview.scss │ │ └── _toolbar.scss ├── tsconfig.json ├── tsconfig.tsbuildinfo ├── vite-environment.d.ts ├── vite.config.ts └── vite.polling.config.ts ├── logsettings.json ├── scripts ├── backup.sh ├── docker-ensure-initdb.sh ├── docker-entrypoint.sh ├── entrypoint.sh ├── env.sh ├── restore.sh └── yt.sh ├── tests ├── StreamMaster.Application.UnitTests │ ├── EPG │ │ └── Commands │ │ │ └── XMLTVBuilderTests.cs │ ├── StreamGroups │ │ ├── StreamGroupServiceCryptoTests.cs │ │ ├── StreamGroupServiceLineupTests.cs │ │ ├── StreamGroupServiceProfileTests.cs │ │ └── StreamGroupServiceTests.cs │ └── StreamMaster.Application.UnitTests.csproj ├── StreamMaster.Infrastructure.UnitTests │ ├── Services │ │ └── LogoServiceTests.cs │ └── StreamMaster.Infrastructure.UnitTests.csproj ├── StreamMaster.SchedulesDirect.Services.UnitTests │ ├── ApiErrorManagerTests.cs │ ├── HttpServiceTests.cs │ └── StreamMaster.SchedulesDirect.Services.UnitTests.csproj └── StreamMaster.Streams.UnitTests │ ├── Channels │ └── ChannelServiceTests.cs │ ├── Plugins │ └── CircularBufferTests.cs │ ├── Services │ └── SwitchToNextStreamServiceTests.cs │ └── StreamMaster.Streams.UnitTests.csproj └── updateAssemblyInfo.js /.dockerignore: -------------------------------------------------------------------------------- 1 | **/.classpath 2 | **/.dockerignore 3 | **/.env 4 | **/.git 5 | **/.gitignore 6 | **/.project 7 | **/.settings 8 | **/.toolstarget 9 | **/.vs 10 | **/.vscode 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/bin 15 | **/charts 16 | **/docker-compose* 17 | **/compose* 18 | **/Dockerfile* 19 | **/node_modules 20 | **/npm-debug.log 21 | **/obj 22 | **/secrets.dev.yaml 23 | **/values.dev.yaml 24 | **/.eslintrc.json 25 | LICENSE 26 | README.md 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Feature Request or Idea 4 | url: https://github.com/carlreid/StreamMaster/discussions/new?category=ideas 5 | about: Open a Discussion for new Features or Ideas 6 | - name: Have a question or need help? 7 | url: https://github.com/carlreid/StreamMaster/discussions/new?category=q-a 8 | about: Please use Discussions for support. 9 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | "Area: API": 2 | - StreamMasterApplication/**/* 3 | 4 | "Area: Parser": 5 | - StreamMaster.M3U8/**/* 6 | - StreamMaster.SchedulesDirect/**/* 7 | 8 | "Area: Db-migration": 9 | - StreamMasterInfrastructure/Persistence/Migrations/* 10 | 11 | "Area: Download Clients": 12 | - src/NzbDrone.Core/Download/Clients/**/* 13 | 14 | "Area: UI": 15 | - StreamMaster.WebUI/**/* 16 | - package.json 17 | - yarn.lock 18 | -------------------------------------------------------------------------------- /.github/workflows/pr-build.yml: -------------------------------------------------------------------------------- 1 | name: PR Docker Build 2 | 3 | on: 4 | pull_request_target: 5 | types: [opened, synchronize, reopened] 6 | 7 | permissions: 8 | contents: read 9 | packages: write 10 | 11 | jobs: 12 | build: 13 | uses: ./.github/workflows/docker-build-shared.yml 14 | with: 15 | version: pr-${{ github.event.pull_request.number }} 16 | build_all: true 17 | release_as_latest: false 18 | secrets: 19 | token: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "dotnet.defaultSolution": "StreamMaster.sln", 3 | "conventionalCommits.scopes": ["build"] 4 | } 5 | -------------------------------------------------------------------------------- /2025-02-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlreid/StreamMaster/a8f8f6cda65138226ea2cfe73c5dd0db3a040c88/2025-02-12.png -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | 6 | -------------------------------------------------------------------------------- /Dockerfile.tests: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/sdk:9.0 AS test 2 | ARG TARGETPLATFORM 3 | ARG TARGETOS 4 | ARG TARGETARCH 5 | ARG TARGETVARIANT 6 | 7 | WORKDIR /src 8 | COPY . . 9 | 10 | RUN echo "Running tests..." && \ 11 | for project in $(find src/tests -type f -name "*.csproj"); do \ 12 | echo "Found test project: $project" && \ 13 | echo "Testing $project..." && \ 14 | dotnet test "$project" -a $TARGETARCH -c Debug --verbosity minimal; \ 15 | done 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@semantic-release/changelog": "^6.0.3", 4 | "@semantic-release/exec": "^7.0.3", 5 | "@semantic-release/git": "^10.0.1", 6 | "all-contributors-cli": "^6.26.1", 7 | "semantic-release": "^24.2.2" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/BuildClientAPI/TS/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace BuildClientAPI.TS; 2 | public static class StringExtensions 3 | { 4 | public static string ToCamelCase(this string str) 5 | { 6 | return !string.IsNullOrEmpty(str) && str.Length > 1 ? char.ToLowerInvariant(str[0]) + str[1..] : str; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/StreamMaster.API/.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "dotnet-ef": { 6 | "version": "9.0.0", 7 | "commands": [ 8 | "dotnet-ef" 9 | ], 10 | "rollForward": false 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /src/StreamMaster.API/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | [assembly: AssemblyVersion("0.0.0.0")] 4 | [assembly: AssemblyFileVersion("0.0.0.0")] 5 | [assembly: AssemblyInformationalVersion("0.15.0.Sha.26eec914019cf799700b4b771b1e28df45b9636d")] -------------------------------------------------------------------------------- /src/StreamMaster.API/Exceptions/InvalidApiKeyException.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.API.Exceptions 2 | { 3 | public class InvalidApiKeyException : Exception 4 | { 5 | public InvalidApiKeyException() 6 | { 7 | } 8 | 9 | public InvalidApiKeyException(string message) 10 | : base(message) 11 | { 12 | } 13 | 14 | public InvalidApiKeyException(string? message, Exception? innerException) : base(message, innerException) 15 | { 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/StreamMaster.API/Fonts/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlreid/StreamMaster/a8f8f6cda65138226ea2cfe73c5dd0db3a040c88/src/StreamMaster.API/Fonts/Roboto-Regular.ttf -------------------------------------------------------------------------------- /src/StreamMaster.API/Helpers/StreamUtil.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.API.Helpers; 2 | 3 | public class StreamUtil; 4 | -------------------------------------------------------------------------------- /src/StreamMaster.API/ReinforcedTypingsConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.API 2 | { 3 | public static class ReinforcedTypingsConfiguration 4 | { 5 | public static void Configure()//ConfigurationBuilder builder) 6 | { 7 | //builder 8 | // .ExportAsInterface() 9 | // .WithMethods(prop => prop.ProfileName == "Mapping", conf => conf.Ignore()) 10 | // .WithPublicProperties(); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/StreamMaster.API/Services/CurrentUserService.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Application.Interfaces; 2 | using System.Security.Claims; 3 | 4 | namespace StreamMaster.API.Services; 5 | 6 | public class CurrentUserService(IHttpContextAccessor httpContextAccessor) : ICurrentUserService 7 | { 8 | public string? UserId => httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier); 9 | } -------------------------------------------------------------------------------- /src/StreamMaster.API/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } -------------------------------------------------------------------------------- /src/StreamMaster.API/appsettings.Production.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } -------------------------------------------------------------------------------- /src/StreamMaster.API/hlssettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } -------------------------------------------------------------------------------- /src/StreamMaster.API/hlssettings.Production.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } -------------------------------------------------------------------------------- /src/StreamMaster.API/libman.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "defaultProvider": "cdnjs", 4 | "libraries": [] 5 | } -------------------------------------------------------------------------------- /src/StreamMaster.API/logsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } -------------------------------------------------------------------------------- /src/StreamMaster.API/logsettings.Production.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } -------------------------------------------------------------------------------- /src/StreamMaster.API/logsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerOutputFormatter": "Error", 6 | "Microsoft": "Warning", 7 | "Microsoft.AspNetCore.SignalR": "Warning", 8 | "Microsoft.AspNetCore.Http.Connections": "Warning", 9 | "Microsoft.EntityFrameworkCore.Query": "Warning", 10 | "System.Net.Http.HttpClient": "Warning", 11 | "StreamMaster.Infrastructure.Authentication.ApiKeyAuthenticationHandler": "Warning", 12 | "StreamMaster.Domain.Cache": "Debug" 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/StreamMaster.API/wwwroot/images/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlreid/StreamMaster/a8f8f6cda65138226ea2cfe73c5dd0db3a040c88/src/StreamMaster.API/wwwroot/images/default.png -------------------------------------------------------------------------------- /src/StreamMaster.API/wwwroot/images/streammaster_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlreid/StreamMaster/a8f8f6cda65138226ea2cfe73c5dd0db3a040c88/src/StreamMaster.API/wwwroot/images/streammaster_logo.png -------------------------------------------------------------------------------- /src/StreamMaster.API/wwwroot/images/transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlreid/StreamMaster/a8f8f6cda65138226ea2cfe73c5dd0db3a040c88/src/StreamMaster.API/wwwroot/images/transparent.png -------------------------------------------------------------------------------- /src/StreamMaster.Application/ChannelGroups/Events/UpdateChannelGroupsEvent.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Application.ChannelGroups.Events; 2 | 3 | public class UpdateChannelGroupsEvent(List channelGroups) : BaseEvent 4 | { 5 | public List ChannelGroups { get; } = channelGroups; 6 | } 7 | -------------------------------------------------------------------------------- /src/StreamMaster.Application/Common/Events/EPGFileAddedEvent.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Domain.Common; 2 | using StreamMaster.Domain.Dto; 3 | 4 | namespace StreamMaster.Application.Common.Events; 5 | 6 | public class EPGFileAddedEvent(EPGFileDto item) : BaseEvent 7 | { 8 | public EPGFileDto Item { get; } = item; 9 | } 10 | -------------------------------------------------------------------------------- /src/StreamMaster.Application/Common/Events/EPGFileDeletedEvent.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Domain.Common; 2 | 3 | namespace StreamMaster.Application.Common.Events; 4 | 5 | public class EPGFileDeletedEvent(int _epgFileId) : BaseEvent 6 | { 7 | public int EPGFileId { get; } = _epgFileId; 8 | } 9 | -------------------------------------------------------------------------------- /src/StreamMaster.Application/Common/Events/M3UFileChangedEvent.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Application.Common.Events; 2 | 3 | public class M3UFileChangedEvent(M3UFileDto m3UFile) : BaseEvent 4 | { 5 | public M3UFileDto M3UFile { get; } = m3UFile; 6 | } 7 | -------------------------------------------------------------------------------- /src/StreamMaster.Application/Common/Events/M3UFileProcessEvent.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Application.Common.Events; 2 | 3 | public class M3UFileProcessEvent(int M3UFileId, bool ForecRun) : BaseEvent 4 | { 5 | public bool ForecRun { get; } = ForecRun; 6 | public int M3UFileId { get; } = M3UFileId; 7 | } 8 | -------------------------------------------------------------------------------- /src/StreamMaster.Application/Common/Models/ChannelNumberPair.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Application.Common.Models; 2 | 3 | [RequireAll] 4 | public class ChannelNumberPair 5 | { 6 | public int ChannelNumber { get; set; } 7 | public string Id { get; set; } = string.Empty; 8 | } 9 | -------------------------------------------------------------------------------- /src/StreamMaster.Application/Common/Models/LineupStatus.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Application.Common.Models; 2 | 3 | public class LineupStatus 4 | { 5 | public int ScanInProgress { get; set; } = 0; 6 | public int ScanPossible { get; set; } = 0; 7 | public string Source { get; set; } = "Cable"; 8 | public string[] SourceList { get; set; } = ["Cable"]; 9 | } -------------------------------------------------------------------------------- /src/StreamMaster.Application/Common/Models/SpecVersion.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace StreamMaster.Application.Common.Models 4 | { 5 | [XmlRoot(ElementName = "specVersion")] 6 | public class SpecVersion 7 | { 8 | [XmlElement(ElementName = "major")] 9 | public int Major; 10 | 11 | [XmlElement(ElementName = "minor")] 12 | public int Minor; 13 | } 14 | } -------------------------------------------------------------------------------- /src/StreamMaster.Application/Common/Models/VideoStreamIdRank.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Domain.Attributes; 2 | 3 | namespace StreamMaster.Application.Common.Models; 4 | 5 | [RequireAll] 6 | public class VideoStreamIdRank 7 | { 8 | public int Rank { get; set; } 9 | public int VideoStreamId { get; set; } 10 | } 11 | -------------------------------------------------------------------------------- /src/StreamMaster.Application/Custom/ICustomPlayListsInterfaces.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Application.Custom; 2 | 3 | public interface ICustomPlayListsTasks 4 | { 5 | ValueTask ScanForCustomPlayLists(CancellationToken cancellationToken = default); 6 | } -------------------------------------------------------------------------------- /src/StreamMaster.Application/EPG/EPGService.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Application.EPG; 2 | 3 | public class EPGService(IRepositoryWrapper repositoryWrapper) : IEPGService 4 | { 5 | public async Task> GetEPGFilesAsync() 6 | { 7 | return await repositoryWrapper.EPGFile.GetQuery().ToListAsync(); 8 | } 9 | } -------------------------------------------------------------------------------- /src/StreamMaster.Application/EPGFiles/EventHandlers/EPGFileAddedEventHandler.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Application.Services; 2 | 3 | namespace StreamMaster.Application.EPGFiles.EventHandlers; 4 | 5 | public class EPGFileAddedEventHandler(IBackgroundTaskQueue taskQueue) 6 | : INotificationHandler 7 | { 8 | public async Task Handle(EPGFileAddedEvent notification, CancellationToken cancellationToken) 9 | { 10 | await taskQueue.ProcessEPGFile(notification.Item.Id, cancellationToken).ConfigureAwait(false); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/StreamMaster.Application/General/IControllerAndHub.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.AspNetCore.Authorization; 3 | using StreamMaster.Application.General.Commands; 4 | 5 | namespace StreamMaster.Application.General 6 | { 7 | public interface IGeneralController 8 | { 9 | Task> SetTestTask(SetTestTaskRequest request); 10 | } 11 | } 12 | 13 | namespace StreamMaster.Application.Hubs 14 | { 15 | public interface IGeneralHub 16 | { 17 | Task SetTestTask(SetTestTaskRequest request); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/StreamMaster.Application/Hub/StreamMasterHub.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | 3 | namespace StreamMaster.Application.Hubs; 4 | 5 | [Authorize(Policy = "SignalR")] 6 | public partial class StreamMasterHub(ISender Sender, IAPIStatsLogger APIStatsLogger, IOptionsMonitor settings) 7 | : Hub; -------------------------------------------------------------------------------- /src/StreamMaster.Application/IBaseRequestHandler.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Domain.Configuration; 2 | 3 | namespace StreamMaster.Application 4 | { 5 | public interface IBaseRequestHandler 6 | { 7 | Task GetSettings(); 8 | } 9 | } -------------------------------------------------------------------------------- /src/StreamMaster.Application/Interfaces/IChannelGroupService.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Application.Interfaces 2 | { 3 | public interface IChannelGroupService 4 | { 5 | Task UpdateChannelGroupCountRequestAsync(ChannelGroupDto ChannelGroup); 6 | Task UpdateChannelGroupCountsRequestAsync(List? ChannelGroups = null); 7 | } 8 | } -------------------------------------------------------------------------------- /src/StreamMaster.Application/Interfaces/ICurrentUserService.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Application.Interfaces; 2 | 3 | public interface ICurrentUserService 4 | { 5 | string? UserId { get; } 6 | } -------------------------------------------------------------------------------- /src/StreamMaster.Application/Interfaces/IDateTime.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Application.Interfaces; 2 | 3 | public interface IDateTime 4 | { 5 | DateTime Now { get; } 6 | } -------------------------------------------------------------------------------- /src/StreamMaster.Application/Interfaces/IFeatureFlagService.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Application.Interfaces; 2 | 3 | public interface IFeatureFlagService 4 | { 5 | bool IsFeatureEnabled(FeatureFlags featureFlag); 6 | } -------------------------------------------------------------------------------- /src/StreamMaster.Application/Interfaces/IM3UToSMStreamsService.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Application.Interfaces 2 | { 3 | public interface IM3UToSMStreamsService 4 | { 5 | IAsyncEnumerable GetSMStreamsFromM3U(M3UFile m3UFile); 6 | } 7 | } -------------------------------------------------------------------------------- /src/StreamMaster.Application/Interfaces/ISharedInterfaces.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Application.Custom; 2 | using StreamMaster.Application.EPGFiles; 3 | using StreamMaster.Application.Logos; 4 | using StreamMaster.Application.M3UFiles; 5 | using StreamMaster.Application.Settings; 6 | using StreamMaster.Application.StreamGroups; 7 | 8 | namespace StreamMaster.Application.Interfaces; 9 | 10 | public interface ISharedTasks : 11 | 12 | IEPGFileTasks, 13 | IM3UFileTasks, 14 | ILogoTasks, 15 | IStreamGroupTasks, 16 | ICustomPlayListsTasks, 17 | ISettingTasks; -------------------------------------------------------------------------------- /src/StreamMaster.Application/Logos/ILogoInterfaces.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Application.Logos; 2 | 3 | public interface ILogoTasks 4 | { 5 | ValueTask CacheEPGChannelLogos(CancellationToken cancellationToken = default); 6 | 7 | ValueTask CacheChannelLogos(CancellationToken cancellationToken = default); 8 | 9 | ValueTask CacheStreamLogos(CancellationToken cancellationToken = default); 10 | 11 | ValueTask ScanForTvLogos(CancellationToken cancellationToken = default); 12 | } -------------------------------------------------------------------------------- /src/StreamMaster.Application/M3UFiles/EventHandlers/M3UFileChangedEventHandler.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Application.M3UFiles.EventHandlers; 2 | 3 | public class M3UFileChangedEventHandler(IDataRefreshService dataRefreshService) : INotificationHandler 4 | { 5 | public async Task Handle(M3UFileChangedEvent notification, CancellationToken cancellationToken) 6 | { 7 | await dataRefreshService.RefreshAllM3U(); 8 | //await _hubContext.ClientChannels.All.M3UFilesRefresh().ConfigureAwait(false); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/StreamMaster.Application/M3UFiles/IM3UInterfaces.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Application.M3UFiles.Commands; 2 | 3 | namespace StreamMaster.Application.M3UFiles; 4 | 5 | public interface IM3UFileTasks 6 | { 7 | ValueTask ProcessM3UFile(ProcessM3UFileRequest pr, bool immediate = false, CancellationToken cancellationToken = default); 8 | 9 | ValueTask ProcessM3UFiles(CancellationToken cancellationToken = default); 10 | 11 | ValueTask ScanDirectoryForM3UFiles(CancellationToken cancellationToken = default); 12 | } 13 | -------------------------------------------------------------------------------- /src/StreamMaster.Application/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "StreamMasterApplication": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "environmentVariables": { 7 | "ASPNETCORE_ENVIRONMENT": "Development" 8 | }, 9 | "applicationUrl": "https://localhost:39617;http://localhost:39618", 10 | "hotReloadEnabled": false, 11 | "nativeDebugging": true 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/StreamMaster.Application/SMStreams/SMStreamService.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Application.SMStreams; 2 | 3 | public class SMStreamService( IRepositoryWrapper repositoryWrapper) 4 | : ISMStreamService 5 | { 6 | public IQueryable GetSMStreamLogos(bool? justHttp = true) 7 | { 8 | return justHttp == true 9 | ? repositoryWrapper.SMStream.GetQuery().Where(a => a.Logo.Contains("://")) 10 | : repositoryWrapper.SMStream.GetQuery().Where(a => !string.IsNullOrEmpty(a.Logo)); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/StreamMaster.Application/Services/IBackgroundTaskQueue.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Application.Common.Models; 2 | using StreamMaster.Application.Interfaces; 3 | 4 | namespace StreamMaster.Application.Services; 5 | 6 | public interface IBackgroundTaskQueue : ISharedTasks 7 | { 8 | bool IsRunning { get; } 9 | ValueTask DeQueueAsync(CancellationToken cancellationToken); 10 | Task> GetQueueStatus(); 11 | bool HasJobs(); 12 | Task SetStart(Guid Id); 13 | Task SetStop(Guid Id); 14 | List GetSMTasks(); 15 | } 16 | -------------------------------------------------------------------------------- /src/StreamMaster.Application/Settings/Hub/StreamMasterHub.Setting.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Application.Settings; 2 | 3 | namespace StreamMaster.Application.Hubs; 4 | 5 | public partial class StreamMasterHub 6 | { 7 | public async Task LogIn(LogInRequest logInRequest) 8 | { 9 | return await Task.FromResult(settings.CurrentValue.AdminUserName == logInRequest.UserName && settings.CurrentValue.AdminPassword == logInRequest.Password); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/StreamMaster.Application/Settings/LogInRequest.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Application.Settings; 2 | 3 | public class LogInRequest 4 | { 5 | public string Password { get; set; } = string.Empty; 6 | public string UserName { get; set; } = string.Empty; 7 | } 8 | -------------------------------------------------------------------------------- /src/StreamMaster.Application/StreamGroups/Commands/CreateSTRMFilesRequest.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Application.StreamGroups.Commands; 2 | 3 | public record CreateSTRMFilesRequest() : IRequest; 4 | 5 | [LogExecutionTimeAspect] 6 | public class CreateSTRMFilesRequestHandler(IStreamGroupService streamGroupService) 7 | : IRequestHandler 8 | { 9 | public async Task Handle(CreateSTRMFilesRequest request, CancellationToken cancellationToken) 10 | { 11 | await streamGroupService.SyncSTRMFilesAsync(cancellationToken); 12 | } 13 | } -------------------------------------------------------------------------------- /src/StreamMaster.Application/StreamGroups/SMFile.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Application.StreamGroups; 2 | 3 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 4 | public record SGFS(string Name, string Url, List SMFS); 5 | 6 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 7 | public record SMFile(string Name, string Url); 8 | -------------------------------------------------------------------------------- /src/StreamMaster.Application/Vs/IControllerAndHub.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.AspNetCore.Authorization; 3 | using StreamMaster.Application.Vs.Queries; 4 | 5 | namespace StreamMaster.Application.Vs 6 | { 7 | public interface IVsController 8 | { 9 | Task>> GetVs(GetVsRequest request); 10 | } 11 | } 12 | 13 | namespace StreamMaster.Application.Hubs 14 | { 15 | public interface IVsHub 16 | { 17 | Task> GetVs(GetVsRequest request); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/StreamMaster.Application/WebSocket/IControllerAndHub.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.AspNetCore.Authorization; 3 | using StreamMaster.Application.WebSocket.Commands; 4 | 5 | namespace StreamMaster.Application.WebSocket 6 | { 7 | public interface IWebSocketController 8 | { 9 | Task> TriggerReload(); 10 | } 11 | } 12 | 13 | namespace StreamMaster.Application.Hubs 14 | { 15 | public interface IWebSocketHub 16 | { 17 | Task TriggerReload(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/StreamMaster.Docs/streammaster/docs/assets/AddHDHR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlreid/StreamMaster/a8f8f6cda65138226ea2cfe73c5dd0db3a040c88/src/StreamMaster.Docs/streammaster/docs/assets/AddHDHR.png -------------------------------------------------------------------------------- /src/StreamMaster.Docs/streammaster/docs/assets/ConfigureHDHR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlreid/StreamMaster/a8f8f6cda65138226ea2cfe73c5dd0db3a040c88/src/StreamMaster.Docs/streammaster/docs/assets/ConfigureHDHR.png -------------------------------------------------------------------------------- /src/StreamMaster.Docs/streammaster/docs/assets/SetXML.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlreid/StreamMaster/a8f8f6cda65138226ea2cfe73c5dd0db3a040c88/src/StreamMaster.Docs/streammaster/docs/assets/SetXML.png -------------------------------------------------------------------------------- /src/StreamMaster.Docs/streammaster/docs/assets/profiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlreid/StreamMaster/a8f8f6cda65138226ea2cfe73c5dd0db3a040c88/src/StreamMaster.Docs/streammaster/docs/assets/profiles.png -------------------------------------------------------------------------------- /src/StreamMaster.Docs/streammaster/docs/assets/sm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlreid/StreamMaster/a8f8f6cda65138226ea2cfe73c5dd0db3a040c88/src/StreamMaster.Docs/streammaster/docs/assets/sm.png -------------------------------------------------------------------------------- /src/StreamMaster.Docs/streammaster/docs/assets/sm_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlreid/StreamMaster/a8f8f6cda65138226ea2cfe73c5dd0db3a040c88/src/StreamMaster.Docs/streammaster/docs/assets/sm_logo.png -------------------------------------------------------------------------------- /src/StreamMaster.Docs/streammaster/docs/en/Contributors.md: -------------------------------------------------------------------------------- 1 | ## Contributor Recognition 🌟 2 | 3 | We appreciate every contribution, no matter how small! All contributors will be added to the [StreamMaster README](https://github.com/carlreid/StreamMaster?tab=readme-ov-file#contributors-). 4 | 5 | Want to learn more about how to contribute? Get started by reading[ the CONTRIBUTING.md file](https://github.com/carlreid/StreamMaster/blob/main/.github/CONTRIBUTING.md). -------------------------------------------------------------------------------- /src/StreamMaster.Docs/streammaster/docs/en/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlreid/StreamMaster/a8f8f6cda65138226ea2cfe73c5dd0db3a040c88/src/StreamMaster.Docs/streammaster/docs/en/image.png -------------------------------------------------------------------------------- /src/StreamMaster.Docs/streammaster/docs/includes/_footer.md: -------------------------------------------------------------------------------- 1 | ## Need Help or Have Questions? 2 | 3 | For any questions, support, or discussions, you can [open a new discussion](https://github.com/carlreid/StreamMaster/discussions). 4 | 5 | --- 6 | 7 | No contribution is too small! If you'd like to improve this documentation, we'd love to hear from you! Your contributions are recognized in the **StreamMaster Documentation Hall of Fame** 🎉. 8 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/API/NoClass.cs: -------------------------------------------------------------------------------- 1 | using Reinforced.Typings.Attributes; 2 | 3 | namespace StreamMaster.Domain.API; 4 | 5 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 6 | public class NoClass; -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Attributes/BuilderIgnore.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Attributes 2 | { 3 | [AttributeUsage(AttributeTargets.Method)] 4 | public class BuilderIgnore : Attribute; 5 | } 6 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Attributes/CreateDirAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Attributes; 2 | 3 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)] 4 | public class CreateDirAttribute : Attribute; 5 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Attributes/IgnoreMapAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Attributes 2 | { 3 | [AttributeUsage(AttributeTargets.Property)] 4 | public class IgnoreMapAttribute : Attribute; 5 | } 6 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Attributes/IndexBy.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Attributes; 2 | 3 | [AttributeUsage(AttributeTargets.Property)] 4 | public class IndexBy(string value) : Attribute 5 | { 6 | public virtual string Value => value; 7 | } 8 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Attributes/JustUpdates.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Attributes 2 | { 3 | [AttributeUsage(AttributeTargets.Method)] 4 | public class JustUpdates : Attribute; 5 | } 6 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Attributes/RequireAll.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Attributes 2 | { 3 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, Inherited = true, AllowMultiple = true)] 4 | public sealed class RequireAllAttribute : Attribute; 5 | } 6 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Attributes/SMAPI.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Attributes; 2 | 3 | [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)] 4 | public class SMAPIAttribute(bool JustHub = false, bool JustController = false, bool Persist = false, bool IsTask = false, bool NoDebug = false) : Attribute 5 | { 6 | public bool IsTask { get; set; } = IsTask; 7 | public bool JustHub { get; set; } = JustHub; 8 | public bool JustController { get; set; } = JustController; 9 | public bool Persist { get; set; } = Persist; 10 | public bool NoDebug { get; set; } = NoDebug; 11 | } 12 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Attributes/SortBy.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Attributes 2 | { 3 | [AttributeUsage(AttributeTargets.Property)] 4 | public class SortBy : Attribute; 5 | } 6 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Authentication/IUserRepository.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Domain.Models; 2 | 3 | namespace StreamMaster.Domain.Authentication; 4 | 5 | public interface IUserRepository 6 | { 7 | User? FindUser(string username); 8 | 9 | User? FindUser(Guid identifier); 10 | 11 | User Insert(User user); 12 | 13 | int SaveChanges(); 14 | } 15 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Common/BaseEntity.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace StreamMaster.Domain.Common; 5 | 6 | public abstract class BaseEntity 7 | { 8 | [Key] 9 | [JsonIgnore] 10 | public int Id { get; set; } 11 | } 12 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Common/BaseEvent.cs: -------------------------------------------------------------------------------- 1 | using MediatR; 2 | 3 | namespace StreamMaster.Domain.Common; 4 | 5 | public abstract class BaseEvent : INotification; 6 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Common/M3UFileIdMaxStream.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Common; 2 | 3 | public class M3UFileIdMaxStream 4 | { 5 | public int M3UFileId { get; set; } 6 | public int MaxStreams { get; set; } 7 | } 8 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Common/ProxyStreamErrorCode.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Common; 2 | 3 | public enum ProxyStreamErrorCode 4 | { 5 | UnknownError, 6 | HttpRequestError, 7 | IoError, 8 | FileNotFound, 9 | ChannelManagerFinished, 10 | HttpError, 11 | Canceled, 12 | DownloadError, 13 | MasterPlayListNotSupported, 14 | ProcessStartFailed, 15 | OperationCancelled, 16 | Timeout 17 | } 18 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Common/SGLineUp.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Common; 2 | 3 | public class SGLineup 4 | { 5 | public string? GuideNumber { get; set; } 6 | public string? GuideName { get; set; } 7 | public string? Station { get; set; } 8 | public string? Logo { get; set; } 9 | public string? URL { get; set; } 10 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Common/ThreadSafeCounter.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Common; 2 | public class ThreadSafeCounter 3 | { 4 | private int count; 5 | 6 | public int Count 7 | { 8 | get { return Volatile.Read(ref count); } 9 | } 10 | 11 | public void Decrement() 12 | { 13 | Interlocked.Decrement(ref count); 14 | } 15 | 16 | public void Increment() 17 | { 18 | Interlocked.Increment(ref count); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Common/UpdateSettingResponse.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Common; 2 | 3 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 4 | public class UpdateSettingResponse 5 | { 6 | public bool NeedsLogOut { get; set; } 7 | public SettingDto? Settings { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Common/Utf8StringWriter.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace StreamMaster.Domain.Common; 4 | 5 | public partial class GetStreamGroupEPGHandler 6 | { 7 | public class Utf8StringWriter : StringWriter 8 | { 9 | public override Encoding Encoding => Encoding.UTF8; 10 | } 11 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Configuration/ErrorCooldownSetting.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.Domain.Configuration 4 | { 5 | public class ErrorCooldownSetting 6 | { 7 | [JsonPropertyName("code")] 8 | public int ErrorCode { get; set; } 9 | 10 | [JsonPropertyName("until")] 11 | public DateTime CooldownUntil { get; set; } 12 | 13 | [JsonPropertyName("reason")] 14 | public string Reason { get; set; } = string.Empty; 15 | } 16 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Configuration/IProfileDict.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Configuration; 2 | 3 | public interface IProfileDict 4 | { 5 | bool IsReadOnly(string ProfileName); 6 | 7 | Dictionary Profiles { get; } 8 | 9 | void AddProfile(string ProfileName, TProfile Profile); 10 | 11 | void AddProfiles(Dictionary profiles); 12 | 13 | void RemoveProfile(string ProfileName); 14 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Crypto/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | 3 | namespace StreamMaster.Domain.Crypto; 4 | public static class StringExtensions 5 | { 6 | public static string ToCleanFileString(this string input) 7 | { 8 | return string.IsNullOrWhiteSpace(input) 9 | ? throw new ArgumentException("Input cannot be null or whitespace.", nameof(input)) 10 | : HttpUtility.HtmlEncode(input).Trim().Replace('+', '-').Replace(' ', '_').Replace('/', '_'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Dto/ChannelGroupDto.cs: -------------------------------------------------------------------------------- 1 | using Reinforced.Typings.Attributes; 2 | 3 | using StreamMaster.Domain.Attributes; 4 | 5 | namespace StreamMaster.Domain.Dto; 6 | 7 | [RequireAll] 8 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 9 | 10 | public class ChannelGroupDto : ChannelGroup, IMapFrom; -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Dto/ChannelGroupIdName.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Dto; 2 | 3 | public class ChannelGroupIdName 4 | { 5 | public int Id { get; set; } 6 | public int TotalCount { get; set; } 7 | public string Name { get; set; } = string.Empty; 8 | } 9 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Dto/ChannelLogoDto.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Dto; 2 | 3 | public class ChannelLogoDto : IconFile 4 | { 5 | public required string EPGId { get; set; } 6 | public int EPGFileId { get; set; } 7 | } 8 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Dto/EPGColor.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Dto; 2 | 3 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 4 | public class EPGColorDto : IMapFrom 5 | { 6 | public int Id { get; set; } 7 | public int EPGNumber { get; set; } 8 | public string StationId { get; set; } = string.Empty; 9 | public string Color { get; set; } = "#FFFFFF"; 10 | } 11 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Dto/EPGFilePreviewDto.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Dto; 2 | 3 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 4 | public class EPGFilePreviewDto 5 | { 6 | public string Id { get; set; } = string.Empty; 7 | public string ChannelLogo { get; set; } = string.Empty; 8 | 9 | //public string ChannelNumber { get; set; } = string.Empty; 10 | public string ChannelName { get; set; } = string.Empty; 11 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Dto/GetChannelGroupVideoStreamCountResponse.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Dto; 2 | 3 | public class ChannelGroupStreamCount 4 | { 5 | public int Id { get; set; } 6 | public int ActiveCount { get; set; } 7 | public int TotalCount { get; set; } 8 | public int HiddenCount { get; set; } 9 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Dto/IDVisible.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Dto; 2 | 3 | public class IDIsHidden 4 | { 5 | public required string Id { get; set; } 6 | public bool IsHidden { get; set; } 7 | } 8 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Dto/IdName.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Domain.Attributes; 2 | 3 | namespace StreamMaster.Domain.Dto; 4 | 5 | [RequireAll] 6 | public class IdName 7 | { 8 | public IdName() { } 9 | 10 | public IdName(string Id, string Name) 11 | { 12 | this.Id = Id; 13 | this.Name = Name; 14 | } 15 | public string Id { get; set; } = string.Empty; 16 | public string Name { get; set; } = string.Empty; 17 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Dto/LogEntryDto.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Domain.Mappings; 2 | using StreamMaster.Domain.Models; 3 | 4 | namespace StreamMaster.Domain.Dto; 5 | 6 | public class LogEntryDto : LogEntry, IMapFrom; 7 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Dto/PagedDto.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Dto; 2 | 3 | public class PagedDto 4 | { 5 | public int CurrentPage { get; } 6 | public int TotalPages { get; } 7 | public int PageSize { get; } 8 | public int TotalCount { get; } 9 | public bool HasPrevious => CurrentPage > 1; 10 | public bool HasNext => CurrentPage < TotalPages; 11 | } 12 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Dto/SDSystemStatus.cs: -------------------------------------------------------------------------------- 1 | using Reinforced.Typings.Attributes; 2 | 3 | namespace StreamMaster.Domain.Dto; 4 | 5 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 6 | public class SDSystemStatus 7 | { 8 | public bool IsSystemReady { get; init; } 9 | } 10 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Dto/SMStreamDto.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace StreamMaster.Domain.Dto; 3 | 4 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 5 | public class SMStreamDto : SMStream, IMapFrom 6 | { 7 | public int Rank { get; set; } 8 | public string RealUrl { get; set; } = string.Empty; 9 | public List ChannelMembership { get; set; } = []; 10 | } 11 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Dto/StreamingServiceStatusDto.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Dto; 2 | 3 | public class StreamingServiceStatusDto 4 | { 5 | public Guid Id { get; set; } 6 | public int MaxClientBufferSingleSendInBytes { get; set; } 7 | public int MaxStreamBufferSingleReadInBytes { get; set; } 8 | public int TotalClients { get; set; } 9 | public double TotalInboundBps { get; set; } 10 | public int TotalStreamWorkers { get; set; } 11 | } 12 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Dto/VideoStreamIsReadOnly.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Dto; 2 | 3 | public class VideoStreamIsReadOnly 4 | { 5 | public int Rank { get; set; } 6 | public bool IsReadOnly { get; set; } 7 | public required string VideoStreamId { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Enums/AuthenticationType.cs: -------------------------------------------------------------------------------- 1 | using Reinforced.Typings.Attributes; 2 | 3 | namespace StreamMaster.Domain.Enums; 4 | 5 | [TsEnum] 6 | public enum AuthenticationType 7 | { 8 | None = 0, 9 | 10 | // Basic = 1, 11 | Forms = 2 12 | } 13 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Enums/FeatureFlags.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Enums; 2 | 3 | public enum FeatureFlags 4 | { 5 | ShortLinks = 0, 6 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Enums/FileDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Enums; 2 | 3 | public class FileDefinition 4 | { 5 | public string DefaultExtension { get; set; } = string.Empty; 6 | public string DirectoryLocation { get; set; } = string.Empty; 7 | public string FileExtensions { get; set; } = string.Empty; 8 | public SMFileTypes SMFileType { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Enums/JobType.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Enums; 2 | 3 | [TsEnum] 4 | 5 | public enum JobType 6 | { 7 | ProcessM3U, 8 | RefreshM3U, 9 | TimerM3U, 10 | ProcessEPG, 11 | RefreshEPG, 12 | UpdateEPG, 13 | UpdateM3U, 14 | TimerEPG, 15 | SDSync, 16 | Backup, 17 | TimerBackup, 18 | EPGRemovedExpiredKeys 19 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Enums/M3UField.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Enums; 2 | 3 | [TsEnum] 4 | public enum M3UField 5 | { 6 | ChannelId = 0, 7 | ChannelName = 1, 8 | ChannelNumber = 2, 9 | 10 | //CUID = 3, 11 | Group = 3, 12 | 13 | Name = 4, 14 | TvgID = 5, 15 | TvgName = 6, 16 | //URL = 8, 17 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Enums/M3UFileStreamURLPrefix.cs: -------------------------------------------------------------------------------- 1 | using Reinforced.Typings.Attributes; 2 | 3 | namespace StreamMaster.Domain.Enums; 4 | 5 | [TsEnum] 6 | public enum M3UFileStreamURLPrefix 7 | { 8 | SystemDefault = 0, 9 | TS = 1, 10 | M3U8 = 2, 11 | } 12 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Enums/M3UKey.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Enums; 2 | 3 | [TsEnum] 4 | 5 | public enum M3UKey 6 | { 7 | URL = 0, 8 | CUID = 1, 9 | ChannelId = 2, 10 | TvgID = 3, 11 | TvgName = 4, 12 | TvgName_TvgID = 5, 13 | Name = 6, 14 | Name_TvgID = 7, 15 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Enums/SMChannelTypeEnum.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Enums; 2 | 3 | [TsEnum] 4 | public enum SMChannelTypeEnum 5 | { 6 | Regular = 0, 7 | MultiView = 1, 8 | Movie = 2, 9 | Intro = 3, 10 | Message = 4, 11 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Enums/SMFileTypes.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Enums; 2 | 3 | [TsEnum] 4 | public enum SMFileTypes 5 | { 6 | M3U = 0, 7 | EPG = 1, 8 | HDHR = 2, 9 | Channel = 3, 10 | M3UStream = 4, 11 | Image = 5, 12 | TvLogo = 6, 13 | Logo = 7, 14 | CustomLogo = 8, 15 | //SDImage = 10, 16 | //SDStationLogo = 11, 17 | CustomPlayList = 9, 18 | CustomPlayListLogo = 10, 19 | //SDProgramLogo = 14, 20 | ProgramLogo = 11 21 | } 22 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Enums/SMQueCommand.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Enums; 2 | 3 | public enum SMQueCommand 4 | { 5 | CacheChannelLogos, 6 | CacheStreamLogos, 7 | CacheEPGChannelLogos, 8 | 9 | EPGRemovedExpiredKeys, 10 | ScanForTvLogos, 11 | 12 | ProcessEPGFile, 13 | ProcessM3UFile, 14 | ProcessM3UFiles, 15 | 16 | ScanDirectoryForEPGFiles, 17 | ScanDirectoryForM3UFiles, 18 | ScanForCustomPlayLists, 19 | 20 | EPGSync, 21 | SetIsSystemReady, 22 | SetTestTask, 23 | 24 | UpdateEntitiesFromIPTVChannels, 25 | CreateSTRMFiles 26 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Enums/SMStreamTypeEnum.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Enums; 2 | 3 | [TsEnum] 4 | public enum SMStreamTypeEnum 5 | { 6 | Regular = 0, 7 | User = 1, 8 | Movie = 2, 9 | Intro = 3, 10 | Message = 4, 11 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Enums/ValidM3USetting.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Enums; 2 | 3 | [TsEnum] 4 | public enum ValidM3USetting 5 | { 6 | NotMapped = 0, 7 | Name = 2, 8 | Group = 3, 9 | ChannelNumber = 4, 10 | ChannelName = 5 11 | } 12 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Enums/VideoStreamHandlers.cs: -------------------------------------------------------------------------------- 1 | using Reinforced.Typings.Attributes; 2 | 3 | namespace StreamMaster.Domain.Enums; 4 | 5 | [TsEnum] 6 | public enum VideoStreamHandlers 7 | { 8 | SystemDefault = 0, 9 | None = 1, 10 | Loop = 2, 11 | } 12 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Events/AsyncEventHandler.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Events; 2 | 3 | public delegate Task AsyncEventHandler(object sender, TEventArgs e); -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Exceptions/APIException.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Exceptions; 2 | 3 | [Serializable] 4 | public class APIException : Exception 5 | { 6 | public APIException(string message) : base(message) 7 | { 8 | } 9 | 10 | public APIException() : base() 11 | { 12 | } 13 | 14 | public APIException(string? message, Exception? innerException) : base(message, innerException) 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Extensions/ConcurrentBagExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Concurrent; 2 | 3 | namespace StreamMaster.Domain.Extensions; 4 | 5 | public static class ConcurrentBagExtensions 6 | { 7 | public static void AddRange(this ConcurrentBag bag, IEnumerable range) 8 | { 9 | foreach (T? item in range) 10 | { 11 | if (item is not null) 12 | { 13 | bag.Add(item); 14 | } 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Extensions/DictionaryExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Extensions; 2 | 3 | public static class DictionaryExtensions 4 | { 5 | public static void AddOrUpdate(this Dictionary dictionary, TKey key, TValue? value) where TKey : notnull 6 | { 7 | if (value is null) 8 | { 9 | return; 10 | } 11 | 12 | if (!dictionary.TryAdd(key, value)) 13 | { 14 | dictionary[key] = value; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Extensions/EnumExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Extensions 2 | { 3 | public static class EnumExtensions 4 | { 5 | public static SMFileTypes GetSMFileTypEnumByValue(this int value, SMFileTypes defaultValue = SMFileTypes.Logo) 6 | { 7 | return Enum.IsDefined(typeof(SMFileTypes), value) 8 | ? (SMFileTypes)value 9 | : defaultValue; 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Extensions/ListComparer.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Extensions; 2 | 3 | public static class ListComparer 4 | { 5 | public static bool AreListsEqual(this List list1, List list2) 6 | { 7 | return list1 == null || list2 == null ? list1 == list2 : list1.Count == list2.Count && !list1.Except(list2).Any(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Extensions/VideoInfoExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Extensions; 2 | 3 | public static class VideoInfoExtensions 4 | { 5 | public static bool IsValid(this VideoInfo? videoInfo) 6 | { 7 | return videoInfo != null && !string.IsNullOrEmpty(videoInfo.StreamName); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Filtering/DataTableFilterMetaData.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.Domain.Filtering; 4 | 5 | public class DataTableFilterMetaData 6 | { 7 | [JsonPropertyName("fieldName")] 8 | public string FieldName { get; set; } = string.Empty; 9 | 10 | [JsonPropertyName("value")] 11 | public object Value { get; set; } = string.Empty; 12 | 13 | [JsonPropertyName("matchMode")] 14 | public string MatchMode { get; set; } = string.Empty; 15 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Logging/ILoggingUtils.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Logging 2 | { 3 | public interface ILoggingUtils 4 | { 5 | string GetLoggableURL(string sourceUrl); 6 | } 7 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/APIKey.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Models 2 | { 3 | public class APIKey 4 | { 5 | public Guid Id { get; set; } 6 | 7 | public string Key { get; set; } 8 | 9 | public string UserId { get; set; } 10 | 11 | public string DeviceName { get; set; } 12 | 13 | public List Scopes { get; set; } 14 | 15 | public DateTime? Expiration { get; set; } 16 | 17 | public DateTime CreatedAt { get; set; } 18 | 19 | public DateTime? LastUsedAt { get; set; } 20 | 21 | public bool IsActive { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/APIKeyResponse.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Models 2 | { 3 | public class APIKeyResponse 4 | { 5 | public Guid Id { get; set; } 6 | 7 | public string Key { get; set; } 8 | 9 | public string DeviceName { get; set; } 10 | 11 | public List Scopes { get; set; } 12 | 13 | public DateTime? Expiration { get; set; } 14 | 15 | public DateTime CreatedAt { get; set; } 16 | 17 | public DateTime? LastUsedAt { get; set; } 18 | 19 | public bool IsActive { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/AddSMStreamToSMChannelRequest.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Models; 2 | 3 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 4 | public record SMChannelStreamRankRequest(int SMChannelId, string SMStreamId, int Rank); 5 | 6 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 7 | public record SMChannelChannelRankRequest(int ParentSMChannelId, int ChildSMChannelId, int Rank); 8 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/CreateAPIKeyRequest.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Models 2 | { 3 | public class CreateAPIKeyRequest 4 | { 5 | public string DeviceName { get; set; } 6 | 7 | public List Scopes { get; set; } 8 | 9 | public DateTime? Expiration { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/Device.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Models 2 | { 3 | public class Device 4 | { 5 | public Guid Id { get; set; } 6 | 7 | public string ApiKeyId { get; set; } 8 | 9 | public string UserId { get; set; } 10 | 11 | public string DeviceType { get; set; } 12 | 13 | public string DeviceId { get; set; } 14 | 15 | public string UserAgent { get; set; } 16 | 17 | public string IPAddress { get; set; } 18 | 19 | public DateTime LastActivity { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/DeviceResponse.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Models 2 | { 3 | public class DeviceResponse 4 | { 5 | public Guid Id { get; set; } 6 | 7 | public string DeviceType { get; set; } 8 | 9 | public string DeviceId { get; set; } 10 | 11 | public string UserAgent { get; set; } 12 | 13 | public string IPAddress { get; set; } 14 | 15 | public DateTime LastActivity { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/DupInfo.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Models; 2 | 3 | public class DupInfo 4 | { 5 | public string Id { get; set; } = ""; 6 | public string Name { get; set; } = ""; 7 | public string M3UFileName { get; set; } = ""; 8 | public int FilePosition { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/HeadendToView.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Models; 2 | 3 | public class HeadendToView 4 | { 5 | public string Id { get; set; } = string.Empty; 6 | public string Country { get; set; } = string.Empty; 7 | public string PostalCode { get; set; } = string.Empty; 8 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/IM3UStream.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Models 2 | { 3 | public interface IM3UStream 4 | { 5 | string CUID { get; set; } 6 | int M3UFileId { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/IconFile.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Models; 2 | 3 | public class IconFile : CacheEntity 4 | { 5 | public IconFile() 6 | { 7 | //DirectoryLocation = FileDefinitions.M3ULogo.DirectoryLocation; 8 | FileExtension = FileDefinitions.Logo.DefaultExtension; 9 | SMFileType = FileDefinitions.Logo.SMFileType; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/IdIntResultWithResponse.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Domain.API; 2 | 3 | namespace StreamMaster.Domain.Models; 4 | 5 | public class IdIntResult 6 | { 7 | public int Id { get; set; } 8 | public required dynamic Result { get; set; } 9 | } 10 | 11 | public class IdIntResultWithResponse : List 12 | { 13 | public APIResponse APIResponse { get; set; } = APIResponse.Ok; 14 | } 15 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/ImagePath.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Models 2 | { 3 | public class ImagePath 4 | { 5 | public SMFileTypes SMFileType { get; set; } 6 | public string FullPath { get; set; } = string.Empty; 7 | public string ReturnName { get; set; } = string.Empty; 8 | } 9 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/LogEntry.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations.Schema; 2 | 3 | using StreamMaster.Domain.Attributes; 4 | 5 | namespace StreamMaster.Domain.Models; 6 | 7 | [RequireAll] 8 | public class LogEntry 9 | { 10 | public int Id { get; set; } 11 | public LogLevel LogLevel { get; set; } 12 | [Column(TypeName = "citext")] 13 | public string LogLevelName => LogLevel.ToString(); 14 | [Column(TypeName = "citext")] 15 | public string Message { get; set; } = string.Empty; 16 | public DateTime TimeStamp { get; set; } 17 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/ProgrammeChannel.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Models; 2 | 3 | public class ProgrammeChannel 4 | { 5 | public string Channel { get; set; } = string.Empty; 6 | public DateTime EndDateTime { get; set; } 7 | public int EPGFileId { get; set; } 8 | public int ProgrammeCount { get; set; } 9 | public DateTime StartDateTime { get; set; } 10 | } 11 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/SDCacheEntry.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Models; 2 | 3 | public class SDCacheEntry 4 | { 5 | public DateTime Timestamp { get; set; } 6 | public required string Command { get; set; } 7 | public required string Content { get; set; } 8 | public required T Data { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/SMMessage.cs: -------------------------------------------------------------------------------- 1 | using Reinforced.Typings.Attributes; 2 | 3 | namespace StreamMaster.Domain.Models; 4 | 5 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 6 | public record SMMessage(string Severity, string Summary, string? Detail); 7 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/StreamAccessInfo.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Models; 2 | public class StreamAccessInfo 3 | { 4 | public required string Key { get; set; } 5 | public required DateTime LastAccessTime { get; set; } 6 | public required TimeSpan InactiveThreshold { get; set; } 7 | public required string SMStreamId { get; set; } 8 | public required double MillisecondsSinceLastUpdate { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/StreamGroupChannelGroup.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Models; 2 | 3 | public class StreamGroupChannelGroup 4 | { 5 | public required ChannelGroup ChannelGroup { get; set; } 6 | public int ChannelGroupId { get; set; } 7 | public required StreamGroup StreamGroup { get; set; } 8 | public int StreamGroupId { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/SystemKeyValue.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | 4 | namespace StreamMaster.Domain.Models; 5 | 6 | public class SystemKeyValue 7 | { 8 | [Key] 9 | public int Id { get; set; } 10 | 11 | [Column(TypeName = "citext")] 12 | public string Key { get; set; } = string.Empty; 13 | [Column(TypeName = "citext")] 14 | public string Value { get; set; } = string.Empty; 15 | } 16 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/TvLogoFile.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Models; 2 | 3 | public class TvLogoFile : IconFile 4 | { 5 | public TvLogoFile() 6 | { 7 | //DirectoryLocation = FileDefinitions.TVLogo.DirectoryLocation; 8 | FileExtension = FileDefinitions.TVLogo.DefaultExtension; 9 | SMFileType = FileDefinitions.TVLogo.SMFileType; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/User.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Models; 2 | 3 | public class User 4 | { 5 | public int Id { get; set; } 6 | public Guid Identifier { get; set; } 7 | public required string Password { get; set; } 8 | public required string Username { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Models/VideoStreamIDRank.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Models; 2 | 3 | public record VideoStreamIDRank(string VideoStreamId, int Rank); 4 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "StreamMaster.Domain": { 4 | "commandName": "Project", 5 | "hotReloadEnabled": false 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Repository/IAPIKeyRepository.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Repository 2 | { 3 | public interface IAPIKeyRepository 4 | { 5 | Task AddAsync(APIKey apiKey); 6 | 7 | Task> GetByUserIdAsync(string userId); 8 | 9 | Task GetByIdAsync(Guid id); 10 | 11 | Task UpdateAsync(APIKey apiKey); 12 | } 13 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Repository/IDeviceRepository.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Repository 2 | { 3 | public interface IDeviceRepository 4 | { 5 | Task> GetByUserIdAsync(string userId); 6 | 7 | Task GetByIdAsync(Guid id); 8 | 9 | Task DeleteAsync(Device device); 10 | 11 | Task AddOrUpdateDeviceAsync(Device device); 12 | } 13 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Services/IAPIKeyService.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Services 2 | { 3 | public interface IAPIKeyService 4 | { 5 | Task CreateKeyAsync(string username, CreateAPIKeyRequest request); 6 | 7 | Task> GetKeysAsync(string username); 8 | 9 | Task RevokeKeyAsync(string username, Guid id); 10 | } 11 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Services/IAPIStatsLogger.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | namespace StreamMaster.Domain.Services 4 | { 5 | public interface IAPIStatsLogger 6 | { 7 | Task DebugAPI(Task task, [CallerMemberName] string callerName = ""); 8 | Task WriteToLogFileAsync(string functionName, string size, string elapsedTime, string message); 9 | } 10 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Services/IBroadcastService.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Services; 2 | 3 | public interface IBroadcastService 4 | { 5 | void StartBroadcasting(); 6 | void StopBroadcasting(); 7 | } 8 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Services/IDeviceService.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Services 2 | { 3 | public interface IDeviceService 4 | { 5 | Task> GetDevicesAsync(string username); 6 | 7 | Task RevokeDeviceAsync(string username, Guid id); 8 | } 9 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Services/IEPGHelper.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Services 2 | { 3 | public interface IEPGHelper 4 | { 5 | (int epgNumber, string stationId) ExtractEPGNumberAndStationId(string epgId); 6 | 7 | bool IsMovie(int epgNumber); 8 | 9 | bool IsSchedulesDirect(int epgNumber); 10 | } 11 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Services/IEPGService.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Services 2 | { 3 | public interface IEPGService 4 | { 5 | Task> GetEPGFilesAsync(); 6 | } 7 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Services/IFileLoggingService.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Services; 2 | 3 | public interface IFileLoggingService 4 | { 5 | void EnqueueLogEntry(string format, params object[] args); 6 | void EnqueueLogEntry(string logEntry); 7 | Task StopLoggingAsync(); 8 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Services/IFileLoggingServiceFactory.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Services; 2 | 3 | public interface IFileLoggingServiceFactory 4 | { 5 | IFileLoggingService Create(string key); 6 | } 7 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Services/IImageDownloadService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Hosting; 2 | 3 | namespace StreamMaster.Domain.Services 4 | { 5 | public interface IImageDownloadService : IHostedService, IDisposable 6 | { 7 | ImageDownloadServiceStatus ImageDownloadServiceStatus { get; } 8 | Task DownloadImageAsync(LogoInfo logoInfo, CancellationToken cancellationToken); 9 | } 10 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Services/IMessageService.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Services 2 | { 3 | public interface IMessageService 4 | { 5 | Task SendError(string message, Exception? ex); 6 | Task SendError(string message, string? header = null); 7 | Task SendInfo(string message, string? header = null); 8 | Task SendMessage(SMMessage smMessage); 9 | Task SendWarning(string message); 10 | Task SendSuccess(string message, string? header = null); 11 | } 12 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Services/IProfileService.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Domain.Configuration; 2 | 3 | namespace StreamMaster.Domain.Services 4 | { 5 | public interface IProfileService 6 | { 7 | OutputProfileDto GetOutputProfile(string? OutputProfileName = null); 8 | CommandProfileDto GetCommandProfile(string? CommandProfileName = null); 9 | List GetCommandProfiles(); 10 | CommandProfileDto GetM3U8OutputProfile(string id); 11 | } 12 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Services/ISMChannelService.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace StreamMaster.Domain.Services 3 | { 4 | public interface ISMChannelService 5 | { 6 | //IQueryable GetlogoInfos(); 7 | IQueryable GetSMStreamLogos(bool? justHttp = true); 8 | } 9 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Services/ISMStreamService.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Services 2 | { 3 | public interface ISMStreamService 4 | { 5 | IQueryable GetSMStreamLogos(bool? justHttp = true); 6 | } 7 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Services/ISMWebSocketManager.cs: -------------------------------------------------------------------------------- 1 |  2 | using Microsoft.AspNetCore.Http; 3 | 4 | namespace StreamMaster.Domain.Services 5 | { 6 | public interface ISMWebSocketManager 7 | { 8 | Task BroadcastReloadAsync(); 9 | Task HandleWebSocketAsync(HttpContext context); 10 | } 11 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Services/IStreamGroupProfileRepository.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Domain.Repository; 2 | 3 | namespace StreamMaster.Domain.Services 4 | { 5 | public interface IStreamGroupProfileRepository : IRepositoryBase 6 | { 7 | Task DeleteStreamGroupProfile(StreamGroupProfile StreamGroupProfile); 8 | Task> GetStreamGroupProfiles(int? StreamGroupId = null); 9 | //void Update(StreamGroupProfile streamGroupProfile); 10 | } 11 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/Sorting/ISortHelper.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Domain.Sorting 2 | { 3 | public interface ISortHelper 4 | { 5 | IQueryable ApplySort(IQueryable entities, string orderByQueryString); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/StreamMaster.Domain/XmltvXml/XmltvActor.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace StreamMaster.Domain.XmltvXml 4 | { 5 | public class XmltvActor 6 | { 7 | [XmlAttribute("role")] 8 | public string? Role { get; set; } 9 | 10 | [XmlText] 11 | public string Actor { get; set; } = string.Empty; 12 | } 13 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/XmltvXml/XmltvAudio.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace StreamMaster.Domain.XmltvXml 4 | { 5 | public class XmltvAudio 6 | { 7 | [XmlElement("present")] 8 | public string? Present { get; set; } 9 | 10 | [XmlElement("stereo")] 11 | public string? Stereo { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/XmltvXml/XmltvEpisodeNum.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace StreamMaster.Domain.XmltvXml 4 | { 5 | public class XmltvEpisodeNum 6 | { 7 | [XmlAttribute("system")] 8 | public string? System { get; set; } 9 | 10 | [XmlText] 11 | public string? Text { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/XmltvXml/XmltvLength.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace StreamMaster.Domain.XmltvXml 4 | { 5 | public class XmltvLength 6 | { 7 | [XmlAttribute("units")] 8 | public string? Units { get; set; } 9 | 10 | [XmlText] 11 | public string? Text { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/XmltvXml/XmltvPreviouslyShown.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace StreamMaster.Domain.XmltvXml 4 | { 5 | public class XmltvPreviouslyShown 6 | { 7 | [XmlAttribute("start")] 8 | public string? Start { get; set; } 9 | 10 | [XmlAttribute("channel")] 11 | public string? Channel { get; set; } 12 | 13 | [XmlText] 14 | public string? Text { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/XmltvXml/XmltvReview.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace StreamMaster.Domain.XmltvXml 4 | { 5 | public class XmltvReview 6 | { 7 | [XmlAttribute("type")] 8 | public string? Type { get; set; } 9 | 10 | [XmlAttribute("source")] 11 | public string? Source { get; set; } 12 | 13 | [XmlAttribute("reviewer")] 14 | public string? Reviewer { get; set; } 15 | 16 | [XmlAttribute("lang")] 17 | public string? Lang { get; set; } 18 | 19 | [XmlText] 20 | public string? Text { get; set; } 21 | } 22 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/XmltvXml/XmltvSubtitles.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace StreamMaster.Domain.XmltvXml 4 | { 5 | public class XmltvSubtitles 6 | { 7 | [XmlElement("language")] 8 | public string? Language { get; set; } 9 | 10 | [XmlAttribute("type")] 11 | public string? Type { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/XmltvXml/XmltvText.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace StreamMaster.Domain.XmltvXml 4 | { 5 | public class XmltvText 6 | { 7 | public XmltvText() 8 | { } 9 | 10 | public XmltvText(string text) 11 | { 12 | Text = text; 13 | } 14 | 15 | [XmlAttribute("lang")] 16 | public string? Language { get; set; } 17 | 18 | [XmlText] 19 | public string? Text { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /src/StreamMaster.Domain/XmltvXml/XmltvVideo.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace StreamMaster.Domain.XmltvXml 4 | { 5 | public class XmltvVideo 6 | { 7 | [XmlElement("present")] 8 | public string? Present { get; set; } 9 | 10 | [XmlElement("colour")] 11 | public string? Colour { get; set; } 12 | 13 | [XmlElement("aspect")] 14 | public string? Aspect { get; set; } 15 | 16 | [XmlElement("quality")] 17 | public string? Quality { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /src/StreamMaster.EPG/ConfigureServices.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | namespace StreamMaster.EPG; 4 | 5 | public static class ConfigureServices 6 | { 7 | public static IServiceCollection AddEPGServices(this IServiceCollection services) 8 | { 9 | services.AddScoped(); 10 | return services; 11 | } 12 | } -------------------------------------------------------------------------------- /src/StreamMaster.Infrastructure.EF.Base/Configurations/SMStreamConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | 4 | namespace StreamMaster.Infrastructure.EF.Base.Configurations 5 | { 6 | public class SMStreamConfiguration : IEntityTypeConfiguration 7 | { 8 | public void Configure(EntityTypeBuilder modelBuilder) 9 | { 10 | modelBuilder.HasKey(stream => stream.Id); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /src/StreamMaster.Infrastructure.EF.Base/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using StreamMaster.Domain.Extensions; 2 | global using StreamMaster.Domain.Models; 3 | global using StreamMaster.Domain.Repository; 4 | global using StreamMaster.SchedulesDirect.Domain.Models; 5 | -------------------------------------------------------------------------------- /src/StreamMaster.Infrastructure.EF.PGSQL.Console/StreamMaster.Infrastructure.EF.PGSQL.Console.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net9.0 4 | 5 | 6 | Exe 7 | true 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/StreamMaster.Infrastructure.EF.PGSQL/RemoveLast-EfMigration.ps1: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Log the migration name 4 | Write-Host "Removing last migration" 5 | 6 | $command = "dotnet ef migrations remove -c PGSQLRepositoryContext" 7 | Invoke-Expression $command 8 | -------------------------------------------------------------------------------- /src/StreamMaster.Infrastructure.EF.PGSQL/Scripts/001_channelgroup_indexes.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION idx_ChannelGroup_indexes() RETURNS VOID AS $$ 2 | BEGIN 3 | CREATE INDEX IF NOT EXISTS idx_Name ON "ChannelGroup" ("Name"); 4 | CREATE INDEX IF NOT EXISTS idx_Name_IsHidden ON "ChannelGroup" ("Name", "IsHidden"); 5 | END; 6 | $$ LANGUAGE plpgsql; 7 | -------------------------------------------------------------------------------- /src/StreamMaster.Infrastructure.EF.PGSQL/Scripts/003_delete_sm_channels.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION delete_sm_channels(channel_ids INTEGER[]) 2 | RETURNS VOID AS $$ 3 | BEGIN 4 | -- Delete links from SMChannelStreamLink 5 | DELETE FROM public."SMChannelStreamLinks" 6 | WHERE "SMChannelId" = ANY(channel_ids); 7 | 8 | -- Delete channels from SMChannel 9 | DELETE FROM public."SMChannels" 10 | WHERE "Id" = ANY(channel_ids); 11 | END; 12 | $$ LANGUAGE plpgsql; 13 | -------------------------------------------------------------------------------- /src/StreamMaster.Infrastructure.EF.PGSQL/Scripts/004_epgfile_indexes.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION idx_EPGFile_indexes() RETURNS VOID AS $$ 2 | BEGIN 3 | CREATE INDEX IF NOT EXISTS idx_epgfiles_url ON "EPGFile" ("Url"); 4 | END; 5 | $$ LANGUAGE plpgsql; 6 | -------------------------------------------------------------------------------- /src/StreamMaster.Infrastructure.EF.PGSQL/Scripts/005_get_unique_smchannel_name.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION get_unique_smchannel_name(sm_channel_name TEXT) 2 | RETURNS TEXT AS $$ 3 | SELECT CASE 4 | WHEN COUNT(*) = 0 THEN sm_channel_name 5 | ELSE sm_channel_name || '.' || ( 6 | COALESCE( 7 | MAX( 8 | SPLIT_PART("Name", '.', 2)::INT 9 | ), 0 10 | ) + 1 11 | ) 12 | END 13 | FROM "SMChannels" 14 | WHERE LOWER("Name") = LOWER(sm_channel_name) 15 | OR LOWER("Name") LIKE LOWER(sm_channel_name) || '.%'; 16 | $$ LANGUAGE sql; 17 | -------------------------------------------------------------------------------- /src/StreamMaster.Infrastructure.EF.PGSQL/Scripts/006_smchannel_indexes.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION idx_SMChannel_indexes() RETURNS VOID AS $$ 2 | BEGIN 3 | CREATE UNIQUE INDEX IF NOT EXISTS idx_smchannels_id ON "SMChannel" ("Id"); 4 | CREATE INDEX IF NOT EXISTS idx_smchannels_group ON "SMChannel" ("Group"); 5 | CREATE INDEX IF NOT EXISTS idx_smchannels_basestreamid ON "SMChannel" ("BaseStreamID"); 6 | CREATE INDEX IF NOT EXISTS idx_SMChannelName ON "SMChannel" ("Name"); 7 | CREATE INDEX IF NOT EXISTS idx_smchannels_channelnumber_id ON "SMChannel" ("ChannelNumber", "Id"); 8 | END; 9 | $$ LANGUAGE plpgsql; 10 | -------------------------------------------------------------------------------- /src/StreamMaster.Infrastructure.EF.PGSQL/Scripts/007_smchannelstreamlink_indexes.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION idx_SMChannelStreamLink_indexes() RETURNS VOID AS $$ 2 | BEGIN 3 | CREATE UNIQUE INDEX IF NOT EXISTS idx_smchannelstreamlinks_smchannelid_smstreamid ON "SMChannelStreamLink" ("SMChannelId", "SMStreamId"); 4 | CREATE INDEX IF NOT EXISTS idx_smchannelstreamlinks_smchannelid_rank ON "SMChannelStreamLink" ("SMChannelId", "Rank"); 5 | CREATE INDEX IF NOT EXISTS idx_smchannelstreamlink_smchannelid ON "SMChannelStreamLink" ("SMChannelId"); 6 | END; 7 | $$ LANGUAGE plpgsql; 8 | -------------------------------------------------------------------------------- /src/StreamMaster.Infrastructure.EF.PGSQL/Scripts/009_streamgroup_indexes.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION idx_StreamGroup_indexes() RETURNS VOID AS $$ 2 | BEGIN 3 | CREATE INDEX IF NOT EXISTS idx_streamgroups_name_id ON "StreamGroup" ("Name", "Id"); 4 | END; 5 | $$ LANGUAGE plpgsql; 6 | -------------------------------------------------------------------------------- /src/StreamMaster.Infrastructure.EF.PGSQL/Scripts/010_streamgroupsmchannellink_indexes.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION idx_StreamGroupSMChannelLink_indexes() RETURNS VOID AS $$ 2 | BEGIN 3 | CREATE UNIQUE INDEX IF NOT EXISTS idx_streamgroupsmchannellink_smchannelid_streamgroupid ON "StreamGroupSMChannelLink" ("SMChannelId", "StreamGroupId"); 4 | CREATE INDEX IF NOT EXISTS IX_StreamGroupSMChannelLink_SMChannelId ON "StreamGroupSMChannelLink" ("SMChannelId"); 5 | END; 6 | $$ LANGUAGE plpgsql; 7 | -------------------------------------------------------------------------------- /src/StreamMaster.Infrastructure/Authentication/LoginResource.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Infrastructure.Authentication 2 | { 3 | public class LoginResource 4 | { 5 | public string Username { get; set; } = string.Empty; 6 | public string Password { get; set; } = string.Empty; 7 | public string RememberMe { get; set; } = string.Empty; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/StreamMaster.Infrastructure/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using Microsoft.Extensions.Options; 2 | 3 | global using StreamMaster.Domain.Models; 4 | 5 | global using StreamMaster.Domain.Services; 6 | -------------------------------------------------------------------------------- /src/StreamMaster.Infrastructure/Logger/FileLoggerDebugProvider.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | 3 | namespace StreamMaster.Infrastructure.Logger; 4 | 5 | public class FileLoggerDebugProvider(IFileLoggingServiceFactory factory) : ILoggerProvider 6 | { 7 | public ILogger CreateLogger(string categoryName) 8 | { 9 | return new FileLoggerDebug(factory); 10 | } 11 | 12 | public void Dispose() 13 | { 14 | GC.SuppressFinalize(this); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/StreamMaster.Infrastructure/Services/Frontend/Mappers/IMapHttpRequestsToDisk.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace StreamMaster.Infrastructure.Services.Frontend.Mappers 4 | { 5 | public interface IMapHttpRequestsToDisk 6 | { 7 | Task MapAsync(string resourceUrl); 8 | bool CanHandle(string resourceUrl); 9 | Task GetResponseAsync(string resourceUrl); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/StreamMaster.Infrastructure/Services/QueueService/BackgroundTaskQueue.CustomPlayList.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Application.Custom; 2 | using StreamMaster.Domain.Enums; 3 | 4 | namespace StreamMaster.Infrastructure.Services.QueueService; 5 | 6 | public partial class BackgroundTaskQueue : ICustomPlayListsTasks 7 | { 8 | public async ValueTask ScanForCustomPlayLists(CancellationToken cancellationToken = default) 9 | { 10 | await QueueAsync(SMQueCommand.ScanForCustomPlayLists, cancellationToken).ConfigureAwait(false); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/StreamMaster.Infrastructure/Services/QueueService/BackgroundTaskQueue.STRM.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Application.StreamGroups; 2 | using StreamMaster.Domain.Enums; 3 | 4 | namespace StreamMaster.Infrastructure.Services.QueueService; 5 | 6 | public partial class BackgroundTaskQueue : IStreamGroupTasks 7 | { 8 | public async ValueTask CreateSTRMFiles(CancellationToken cancellationToken = default) 9 | { 10 | await QueueAsync(SMQueCommand.CreateSTRMFiles, cancellationToken).ConfigureAwait(false); 11 | } 12 | } -------------------------------------------------------------------------------- /src/StreamMaster.Logging/Loggers.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Logging; 2 | public class StatsLogger; 3 | public class Dist_Logger; 4 | public class CircularBufferLogger; 5 | public class ReadsLogger; 6 | public class WriteLogger; 7 | public class WaitsLogger; 8 | public class ImageQLogger; 9 | public class EPGImportLogger; -------------------------------------------------------------------------------- /src/StreamMaster.Logging/StreamMaster.Logging.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/StreamMaster.PlayList/ConfigureServices.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | namespace StreamMaster.PlayList; 3 | 4 | public static class ConfigureServices 5 | { 6 | public static IServiceCollection AddCustomPlayListServices(this IServiceCollection services) 7 | { 8 | _ = services.AddSingleton(); 9 | _ = services.AddSingleton(); 10 | _ = services.AddSingleton(); 11 | 12 | return services; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/StreamMaster.PlayList/IIntroPlayListBuilder.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.PlayList.Models; 2 | 3 | namespace StreamMaster.PlayList 4 | { 5 | public interface IIntroPlayListBuilder 6 | { 7 | int IntroCount { get; } 8 | 9 | string GetIntroLogo(string introFileName); 10 | CustomPlayList? GetIntroPlayList(string Name); 11 | List GetIntroPlayLists(); 12 | CustomStreamNfo? GetRandomIntro(int? avoidIndex = null); 13 | string GetRandomSMStreamIntro(); 14 | } 15 | } -------------------------------------------------------------------------------- /src/StreamMaster.PlayList/INfoFileReader.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.PlayList.Models; 2 | 3 | namespace StreamMaster.PlayList 4 | { 5 | public interface INfoFileReader 6 | { 7 | Movie? ReadNfoFile(string filePath); 8 | } 9 | } -------------------------------------------------------------------------------- /src/StreamMaster.PlayList/Models/CustomPlayList.cs: -------------------------------------------------------------------------------- 1 | using Reinforced.Typings.Attributes; 2 | 3 | namespace StreamMaster.PlayList.Models; 4 | 5 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 6 | public class CustomPlayList 7 | { 8 | public string Name { get; set; } = string.Empty; 9 | public string Logo { get; set; } = string.Empty; 10 | public Movie? FolderNfo { get; set; } 11 | public List CustomStreamNfos { get; set; } = []; 12 | } 13 | -------------------------------------------------------------------------------- /src/StreamMaster.PlayList/Models/Fanart.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | using Reinforced.Typings.Attributes; 4 | 5 | namespace StreamMaster.PlayList.Models; 6 | 7 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 8 | [XmlRoot(ElementName = "fanart")] 9 | public class Fanart 10 | { 11 | [XmlElement(ElementName = "thumb")] 12 | public Thumb? Thumb { get; set; } 13 | } 14 | -------------------------------------------------------------------------------- /src/StreamMaster.PlayList/Models/Fileinfo.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | using Reinforced.Typings.Attributes; 4 | 5 | namespace StreamMaster.PlayList.Models; 6 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 7 | [XmlRoot(ElementName = "fileinfo")] 8 | public class Fileinfo 9 | { 10 | [XmlElement(ElementName = "streamdetails")] 11 | public Streamdetails? Streamdetails { get; set; } 12 | } 13 | -------------------------------------------------------------------------------- /src/StreamMaster.PlayList/Models/Ratings.cs: -------------------------------------------------------------------------------- 1 | using Reinforced.Typings.Attributes; 2 | 3 | using System.Xml.Serialization; 4 | 5 | namespace StreamMaster.PlayList.Models; 6 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 7 | [XmlRoot(ElementName = "ratings")] 8 | public class Ratings 9 | { 10 | [XmlElement(ElementName = "rating")] 11 | public List? Rating { get; set; } 12 | } 13 | -------------------------------------------------------------------------------- /src/StreamMaster.PlayList/Models/Set.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | using Reinforced.Typings.Attributes; 4 | 5 | namespace StreamMaster.PlayList.Models; 6 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 7 | [XmlRoot(ElementName = "set")] 8 | public class Set 9 | { 10 | [XmlElement(ElementName = "name")] 11 | public string? Name { get; set; } 12 | [XmlElement(ElementName = "overview")] 13 | public string? Overview { get; set; } 14 | } 15 | -------------------------------------------------------------------------------- /src/StreamMaster.PlayList/Models/Subtitle.cs: -------------------------------------------------------------------------------- 1 | using Reinforced.Typings.Attributes; 2 | 3 | using System.Xml.Serialization; 4 | 5 | namespace StreamMaster.PlayList.Models; 6 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 7 | [XmlRoot(ElementName = "subtitle")] 8 | public class Subtitle 9 | { 10 | [XmlElement(ElementName = "language")] 11 | public string? Language { get; set; } 12 | } 13 | -------------------------------------------------------------------------------- /src/StreamMaster.PlayList/Models/Thumb.cs: -------------------------------------------------------------------------------- 1 | using Reinforced.Typings.Attributes; 2 | 3 | using System.Xml.Serialization; 4 | 5 | namespace StreamMaster.PlayList.Models; 6 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 7 | [XmlRoot(ElementName = "thumb")] 8 | public class Thumb 9 | { 10 | [XmlAttribute(AttributeName = "aspect")] 11 | public string? Aspect { get; set; } 12 | [XmlAttribute(AttributeName = "preview")] 13 | public string? Preview { get; set; } 14 | [XmlText] 15 | public string? Text { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/StreamMaster.PlayList/Models/Uniqueid.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | using Reinforced.Typings.Attributes; 4 | 5 | namespace StreamMaster.PlayList.Models; 6 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 7 | [XmlRoot(ElementName = "uniqueid")] 8 | public class Uniqueid 9 | { 10 | [XmlAttribute(AttributeName = "type")] 11 | public string? Type { get; set; } 12 | [XmlAttribute(AttributeName = "default")] 13 | public string? Default { get; set; } 14 | [XmlText] 15 | public string? Text { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Dto/ProgrammeNameDto.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Domain.Attributes; 2 | using StreamMaster.Domain.Mappings; 3 | 4 | namespace StreamMaster.SchedulesDirect.Domain.Dto; 5 | 6 | [RequireAll] 7 | public class ProgrammeNameDto : IMapFrom 8 | { 9 | public string Id => Channel; 10 | public string Channel { get; set; } = string.Empty; 11 | public string ChannelName { get; set; } = string.Empty; 12 | public string DisplayName { get; set; } = string.Empty; 13 | } 14 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Enums/APIMethod.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Enums; 2 | 3 | public enum APIMethod 4 | { 5 | GET, 6 | POST, 7 | PUT, 8 | DELETE, 9 | UPCFG, 10 | } 11 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Enums/ImageType.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Enums 2 | { 3 | public enum ImageType 4 | { 5 | Program, 6 | Movie, 7 | Season, 8 | Series 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Enums/KeywordGroupsEnum.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Enums; 2 | public enum KeywordGroupsEnum { EDUCATIONAL, KIDS, MOVIES, MUSIC, NEWS, PAIDPROGRAMMING, PREMIERES, REALITY, SERIES, SPECIAL, SPORTS, UNKNOWN }; 3 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using Reinforced.Typings.Attributes; 2 | 3 | global using StreamMaster.Domain.Configuration; 4 | global using StreamMaster.SchedulesDirect.Domain.JsonClasses; 5 | global using StreamMaster.SchedulesDirect.Domain.Models; 6 | global using StreamMaster.Domain.XmltvXml; 7 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Interfaces/ICustomStreamData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Concurrent; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.Interfaces; 4 | 5 | public interface ICustomStreamData 6 | { 7 | ConcurrentDictionary Services { get; set; } 8 | MxfService FindOrCreateService(string stationId); 9 | 10 | MxfService? GetService(string stationId); 11 | 12 | void RemoveService(string stationId); 13 | void ResetLists(); 14 | } 15 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Interfaces/IDescriptionService.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Interfaces 2 | { 3 | public interface IDescriptionService : IEPGCached, IDisposable 4 | { 5 | Task BuildGenericSeriesInfoDescriptionsAsync(CancellationToken cancellationToken); 6 | } 7 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Interfaces/IEPGCached.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Interfaces; 2 | 3 | public interface IEPGCached 4 | { 5 | List GetExpiredKeys(); 6 | void RemovedExpiredKeys(List? keysToDelete = null); 7 | //void ClearCache(); 8 | //void ResetCache(); 9 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Interfaces/IEpisodeImages.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Interfaces 2 | { 3 | public interface IEpisodeImages : IEPGCached, IDisposable 4 | { 5 | Task ProcessArtAsync(CancellationToken cancellationToken); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Interfaces/ILineupService.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Interfaces 2 | { 3 | public interface ILineupService : IEPGCached, IDisposable 4 | { 5 | Task BuildLineupServicesAsync(CancellationToken cancellationToken = default); 6 | 7 | Task> GetStationPreviews(CancellationToken cancellationToken); 8 | } 9 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Interfaces/IMovieImages.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Interfaces 2 | { 3 | public interface IMovieImages : IEPGCached, IDisposable 4 | { 5 | Task ProcessArtAsync(CancellationToken cancellationToken); 6 | } 7 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Interfaces/IProgramService.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Interfaces 2 | { 3 | public interface IProgramService : IDisposable, IEPGCached 4 | { 5 | Task BuildProgramEntriesAsync(CancellationToken cancellationToken); 6 | } 7 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Interfaces/ISDXMLTVBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Interfaces 2 | { 3 | public interface ISDXMLTVBuilder 4 | { 5 | XMLTV? CreateSDXmlTv(); 6 | } 7 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Interfaces/IScheduleService.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Interfaces 2 | { 3 | public interface IScheduleService : IEPGCached 4 | { 5 | Task BuildScheduleAndProgramEntriesAsync(CancellationToken cancellationToken); 6 | } 7 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Interfaces/ISchedulesDirect.cs: -------------------------------------------------------------------------------- 1 |  2 | using StreamMaster.Domain.API; 3 | 4 | namespace StreamMaster.SchedulesDirect.Domain.Interfaces; 5 | 6 | public interface ISchedulesDirect 7 | { 8 | void RemovedExpiredKeys(); 9 | void ResetAllEPGCaches(); 10 | Task SDSync(CancellationToken cancellationToken); 11 | } 12 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Interfaces/ISeasonImages.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Interfaces 2 | { 3 | public interface ISeasonImages : IEPGCached 4 | { 5 | Task ProcessArtAsync(CancellationToken cancellationToken); 6 | } 7 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Interfaces/ISeriesImages.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Interfaces 2 | { 3 | public interface ISeriesImages : IEPGCached, IDisposable 4 | { 5 | //NameValueCollection SportsSeries { get; set; } 6 | Task ProcessArtAsync(CancellationToken cancellationToken); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Interfaces/ISportsImages.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Interfaces 2 | { 3 | public interface ISportsImages : IEPGCached, IDisposable 4 | { 5 | List SportEvents { get; set; } 6 | 7 | Task ProcessArtAsync(CancellationToken cancellationToken); 8 | } 9 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Interfaces/IXMLTVBuilder.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Domain.Models; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.Interfaces; 4 | public interface IXMLTVBuilder 5 | { 6 | Task CreateXmlTv(List videoStreamConfigs, CancellationToken cancellationToken); 7 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Interfaces/IXmltv2Mxf.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Interfaces 2 | { 3 | public interface IXmltv2Mxf 4 | { 5 | //Task ConvertToXMLTVAsync(string filepath, int EPGNumber); 6 | } 7 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Interfaces/IXmltvChannelBuilder.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Domain.Models; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.Interfaces 4 | { 5 | public interface IXmltvChannelBuilder 6 | { 7 | XmltvChannel BuildXmltvChannel(MxfService service, bool isOG); 8 | XmltvChannel BuildXmltvChannel(XmltvChannel xmltvChannel, VideoStreamConfig videoStreamConfig); 9 | } 10 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Interfaces/IXmltvProgramBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Interfaces 2 | { 3 | public interface IXmltvProgramBuilder 4 | { 5 | XmltvProgramme BuildXmltvProgram(MxfScheduleEntry scheduleEntry, string channelId, int timeShift, string baseUrl); 6 | } 7 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/JsonClasses/AddRemoveLineups.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.JsonClasses 4 | { 5 | public class AddRemoveLineupResponse : BaseResponse 6 | { 7 | [JsonPropertyName("changesRemaining")] 8 | public int ChangesRemaining { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/JsonClasses/GenericDescriptions.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.JsonClasses 4 | { 5 | public class GenericDescription : BaseResponse 6 | { 7 | [JsonPropertyName("startAirdate")] 8 | public string StartAirdate { get; set; } = string.Empty; 9 | 10 | [JsonPropertyName("description100")] 11 | public string? Description100 { get; set; } 12 | 13 | [JsonPropertyName("description1000")] 14 | public string? Description1000 { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/JsonClasses/HeadendLineup.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.JsonClasses 4 | { 5 | public class HeadendLineup 6 | { 7 | [JsonPropertyName("name")] 8 | public string Name { get; set; } = string.Empty; 9 | 10 | [JsonPropertyName("lineup")] 11 | public string Lineup { get; set; } = string.Empty; 12 | 13 | [JsonPropertyName("uri")] 14 | public string Uri { get; set; } = string.Empty; 15 | } 16 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/JsonClasses/LineupResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.JsonClasses; 4 | 5 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 6 | public class LineupResponse : BaseResponse 7 | { 8 | [JsonPropertyName("lineups")] 9 | // //[JsonConverter(typeof(SingleOrListConverter))] 10 | public List Lineups { get; set; } = []; 11 | } 12 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/JsonClasses/ProgramDescription.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.JsonClasses 4 | { 5 | public class ProgramDescription 6 | { 7 | [JsonPropertyName("descriptionLanguage")] 8 | public string DescriptionLanguage { get; set; } = string.Empty; 9 | 10 | [JsonPropertyName("description")] 11 | public string Description { get; set; } = string.Empty; 12 | } 13 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/JsonClasses/ProgramEventDetailsTeam.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.JsonClasses 4 | { 5 | public class ProgramEventDetailsTeam 6 | { 7 | [JsonPropertyName("name")] 8 | public string Name { get; set; } = string.Empty; 9 | 10 | [JsonPropertyName("isHome")] 11 | public bool IsHome { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/JsonClasses/ProgramMetadata.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.JsonClasses 4 | { 5 | public class ProgramMetadata : BaseResponse 6 | { 7 | [JsonPropertyName("programID")] 8 | public string ProgramId { get; set; } = string.Empty; 9 | 10 | [JsonPropertyName("data")] 11 | [JsonConverter(typeof(SingleOrListConverter))] 12 | public List Data { get; set; } = []; 13 | } 14 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/JsonClasses/ProgramRecommendation.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.JsonClasses 4 | { 5 | public class ProgramRecommendation 6 | { 7 | [JsonPropertyName("programID")] 8 | public string ProgramId { get; set; } = string.Empty; 9 | 10 | [JsonPropertyName("title120")] 11 | public string Title120 { get; set; } = string.Empty; 12 | } 13 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/JsonClasses/ProgramTitle.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.JsonClasses 4 | { 5 | public class ProgramTitle 6 | { 7 | [JsonPropertyName("title120")] 8 | public string Title120 { get; set; } = string.Empty; 9 | 10 | [JsonPropertyName("titleLanguage")] 11 | public string TitleLanguage { get; set; } = string.Empty; 12 | } 13 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/JsonClasses/ScheduleMd5Response.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.JsonClasses 4 | { 5 | public class ScheduleMd5Response : BaseResponse 6 | { 7 | [JsonPropertyName("lastModified")] 8 | public string LastModified { get; set; } = string.Empty; 9 | 10 | [JsonPropertyName("md5")] 11 | public string Md5 { get; set; } = string.Empty; 12 | } 13 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/JsonClasses/ScheduleMetadata.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.JsonClasses; 4 | 5 | public class ScheduleMetadata 6 | { 7 | [JsonPropertyName("code")] 8 | public int Code { get; set; } 9 | 10 | [JsonPropertyName("modified")] 11 | public string Modified { get; set; } = string.Empty; 12 | 13 | [JsonPropertyName("md5")] 14 | public string Md5 { get; set; } = string.Empty; 15 | 16 | [JsonPropertyName("startDate")] 17 | public string StartDate { get; set; } = string.Empty; 18 | } 19 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/JsonClasses/ScheduleMultipart.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.JsonClasses; 4 | 5 | public class ScheduleMultipart 6 | { 7 | [JsonPropertyName("partNumber")] 8 | public int PartNumber { get; set; } 9 | 10 | [JsonPropertyName("totalParts")] 11 | public int TotalParts { get; set; } 12 | } 13 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/JsonClasses/ScheduleRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.JsonClasses 4 | { 5 | public class ScheduleRequest 6 | { 7 | [JsonPropertyName("stationID")] 8 | public string StationId { get; set; } = string.Empty; 9 | 10 | [JsonPropertyName("date")] 11 | //[JsonConverter(typeof(SingleOrArrayConverter))] 12 | public string[] Date { get; set; } = []; 13 | } 14 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/JsonClasses/ScheduleTvRating.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.JsonClasses; 4 | 5 | public class ScheduleTvRating 6 | { 7 | [JsonPropertyName("body")] 8 | public string Body { get; set; } = string.Empty; 9 | 10 | [JsonPropertyName("code")] 11 | public string Code { get; set; } = string.Empty; 12 | 13 | [JsonPropertyName("country")] 14 | public string Country { get; set; } = string.Empty; 15 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/JsonClasses/StatusAccount.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.JsonClasses 4 | { 5 | public class StatusAccount 6 | { 7 | [JsonPropertyName("expires")] 8 | public DateTime Expires { get; set; } = DateTime.MinValue; 9 | 10 | [JsonPropertyName("messages")] 11 | //[JsonConverter(typeof(SingleOrArrayConverter))] 12 | public List Messages { get; set; } = []; 13 | 14 | [JsonPropertyName("maxLineups")] 15 | public int MaxLineups { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/JsonClasses/SystemStatus.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.JsonClasses 4 | { 5 | public class SystemStatus 6 | { 7 | [JsonPropertyName("date")] 8 | public string Date { get; set; } = string.Empty; 9 | 10 | [JsonPropertyName("status")] 11 | public string Status { get; set; } = string.Empty; 12 | 13 | [JsonPropertyName("message")] 14 | public string Message { get; set; } = string.Empty; 15 | } 16 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/JsonClasses/Token.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.JsonClasses 4 | { 5 | public class TokenRequest 6 | { 7 | [JsonPropertyName("username")] 8 | public string Username { get; set; } = string.Empty; 9 | 10 | [JsonPropertyName("password")] 11 | public string PasswordHash { get; set; } = string.Empty; 12 | } 13 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/JsonClasses/TokenResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.JsonClasses 4 | { 5 | public class TokenResponse : BaseResponse 6 | { 7 | [JsonPropertyName("token")] 8 | public string Token { get; set; } = string.Empty; 9 | } 10 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Models/Broadcaster.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.Models; 4 | 5 | public class Broadcaster 6 | { 7 | [JsonPropertyName("city")] 8 | public string? City { get; set; } 9 | 10 | [JsonPropertyName("state")] 11 | public string? State { get; set; } 12 | 13 | [JsonPropertyName("postalcode")] 14 | public string? Postalcode { get; set; } 15 | 16 | [JsonPropertyName("country")] 17 | public string? Country { get; set; } 18 | } 19 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Models/CountryData.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Models; 2 | 3 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 4 | public class CountryData 5 | { 6 | public string? Id => Key; 7 | public string? Key { get; set; } 8 | public List? Countries { get; set; } 9 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Models/ImageInfo.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Models; 2 | 3 | public class ImageInfo(string programId, string iconUri, string realUrl, string fullName, int width, int height) 4 | { 5 | public string ProgramId { get; set; } = programId; 6 | public string IconUri { get; set; } = iconUri; 7 | public string RealUrl { get; set; } = realUrl; 8 | public string FullName { get; set; } = fullName; 9 | public int Width { get; set; } = width; 10 | public int Height { get; set; } = height; 11 | } 12 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Models/LineUpResult.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace StreamMaster.SchedulesDirect.Domain.Models; 4 | 5 | [TsInterface(AutoI = false, IncludeNamespace = false, FlattenHierarchy = true, AutoExportMethods = false)] 6 | public class LineupResult 7 | { 8 | [JsonPropertyName("map")] 9 | public List? Map { get; set; } 10 | 11 | [JsonPropertyName("stations")] 12 | public List Stations { get; set; } = []; 13 | 14 | [JsonPropertyName("metadata")] 15 | public Metadata? Metadata { get; set; } 16 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Models/SDGetToken.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Models; 2 | 3 | public class SDGetToken 4 | { 5 | public int Code { get; set; } 6 | public DateTime Datetime { get; set; } 7 | public string? Message { get; set; } 8 | public string? ServerID { get; set; } 9 | public string? Token { get; set; } 10 | } 11 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/Models/SDTokenFile.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain.Models; 2 | 3 | public class SDTokenFile 4 | { 5 | public string? Token { get; set; } 6 | public DateTime TokenDateTime { get; set; } 7 | public DateTime LockOutTokenDateTime { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Domain/SDAPIConfig.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Domain 2 | { 3 | public static class SDAPIConfig 4 | { 5 | public static readonly int MaxQueries = 1250; 6 | public static readonly int MaxDescriptionQueries = 500; 7 | public static readonly int MaxImgQueries = 125; 8 | public static readonly int MaxParallelDownloads = 8; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Services/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using Microsoft.Extensions.Logging; 2 | global using Microsoft.Extensions.Options; 3 | 4 | global using StreamMaster.Domain.Common; 5 | global using StreamMaster.SchedulesDirect.Domain; 6 | global using StreamMaster.SchedulesDirect.Domain.Enums; 7 | global using StreamMaster.SchedulesDirect.Domain.Interfaces; 8 | global using StreamMaster.SchedulesDirect.Domain.JsonClasses; 9 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Services/TokenRefreshException.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Services; 2 | 3 | public class TokenRefreshException : Exception 4 | { 5 | public TokenRefreshException(string message) : base(message) { } 6 | 7 | public TokenRefreshException() : base() 8 | { 9 | } 10 | 11 | public TokenRefreshException(string? message, Exception? innerException) : base(message, innerException) 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect.Services/TokenValidationException.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Services; 2 | 3 | public class TokenValidationException : Exception 4 | { 5 | public TokenValidationException(string message) : base(message) { } 6 | 7 | public TokenValidationException() : base() 8 | { 9 | } 10 | 11 | public TokenValidationException(string? message, Exception? innerException) : base(message, innerException) 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect/Data/SchedulesDirectData.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Data; 2 | 3 | public partial class SchedulesDirectData(int EPGNumber) : ISchedulesDirectData 4 | { 5 | public int EPGNumber { get; set; } = EPGNumber; 6 | 7 | public void ResetLists() 8 | { 9 | Lineups.Clear(); 10 | 11 | Services.Clear(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect/Helpers/SDExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.SchedulesDirect.Helpers; 2 | 3 | public static class SDExtensions 4 | { 5 | public static List? CheckStatus(this UserStatus status) 6 | { 7 | List ret = []; 8 | 9 | foreach (StatusLineup lineup in status.Lineups) 10 | { 11 | if (lineup.IsDeleted) 12 | { 13 | ret.Add($"Lineup {lineup.Lineup} is deleted"); 14 | } 15 | } 16 | 17 | return ret.Count != 0 ? ret : null; 18 | } 19 | } -------------------------------------------------------------------------------- /src/StreamMaster.SchedulesDirect/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "StreamMaster.SchedulesDirect": { 4 | "commandName": "Project", 5 | "hotReloadEnabled": false, 6 | "nativeDebugging": true 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /src/StreamMaster.Streams.Domain/Args/ProcessExitEventArgs.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Streams.Domain.Args; 2 | 3 | public class ProcessExitEventArgs : EventArgs 4 | { 5 | public int ExitCode { get; set; } 6 | } 7 | -------------------------------------------------------------------------------- /src/StreamMaster.Streams.Domain/Events/StreamTimedOut.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Streams.Domain.Events; 2 | 3 | public class StreamTimedOut(string uniqueRequestId, DateTime timeOfTimeout) : EventArgs 4 | { 5 | public string UniqueRequestId { get; } = uniqueRequestId; 6 | public DateTime TimeOfTimeout { get; } = timeOfTimeout; 7 | } 8 | -------------------------------------------------------------------------------- /src/StreamMaster.Streams.Domain/Exceptions/SourceBroadcasterNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Streams.Domain.Exceptions 2 | { 3 | public class SourceBroadcasterNotFoundException : Exception 4 | { 5 | public SourceBroadcasterNotFoundException(string message) : base(message) 6 | { 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /src/StreamMaster.Streams.Domain/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using StreamMaster.Domain.Common; 2 | global using StreamMaster.Domain.Dto; 3 | global using StreamMaster.Streams.Domain.Interfaces; 4 | global using StreamMaster.Streams.Domain.Models; 5 | -------------------------------------------------------------------------------- /src/StreamMaster.Streams.Domain/Interfaces/ICommandStream.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Streams.Domain.Interfaces; 2 | public interface ICommandStream : ISMStream; 3 | -------------------------------------------------------------------------------- /src/StreamMaster.Streams.Domain/Interfaces/ICustomPlayListStream.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Streams.Domain.Interfaces; 2 | 3 | public interface ICustomPlayListStream : ISMStream; -------------------------------------------------------------------------------- /src/StreamMaster.Streams.Domain/Interfaces/IDubcer.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Channels; 2 | 3 | namespace StreamMaster.Streams.Domain.Interfaces; 4 | public interface IDubcer 5 | { 6 | void DubcerChannels(ChannelReader channelReader, ChannelWriter channelWriter, CancellationToken cancellationToken); 7 | } -------------------------------------------------------------------------------- /src/StreamMaster.Streams.Domain/Interfaces/IHTTPStream.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Streams.Domain.Interfaces; 2 | 3 | public interface IHTTPStream : ISMStream; -------------------------------------------------------------------------------- /src/StreamMaster.Streams.Domain/Interfaces/IIntroStatus.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Streams.Domain.Interfaces; 2 | 3 | public interface IIntroStatus 4 | { 5 | int IntroIndex { get; set; } 6 | bool PlayedIntro { get; set; } 7 | bool IsFirst { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/StreamMaster.Streams.Domain/Interfaces/ISourceName.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Streams.Domain.Interfaces; 2 | 3 | public interface ISourceName 4 | { 5 | string SourceName { get; } 6 | } 7 | -------------------------------------------------------------------------------- /src/StreamMaster.Streams.Domain/Interfaces/IStreamConnectionService.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Streams.Domain.Metrics; 2 | 3 | namespace StreamMaster.Streams.Domain.Interfaces 4 | { 5 | public interface IStreamConnectionService 6 | { 7 | StreamConnectionMetricManager GetOrAdd(string id, string streamUrl); 8 | StreamConnectionMetricManager? Get(string id); 9 | List GetMetrics(); 10 | void Remove(string id); 11 | } 12 | } -------------------------------------------------------------------------------- /src/StreamMaster.Streams.Domain/Interfaces/IStreamHandlerMetrics.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Streams.Domain.Interfaces 2 | { 3 | public interface IStreamHandlerMetrics 4 | { 5 | double AverageLatency { get; set; } 6 | long BytesRead { get; set; } 7 | long BytesWritten { get; set; } 8 | int ErrorCount { get; set; } 9 | double Kbps { get; set; } 10 | DateTime StartTime { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /src/StreamMaster.Streams.Domain/Interfaces/IStreamStats.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Streams.Domain.Metrics; 2 | 3 | using System.Xml.Serialization; 4 | 5 | namespace StreamMaster.Streams.Domain.Interfaces; 6 | public interface IStreamStats 7 | { 8 | //double GetAverageLatency(); 9 | //long GetBytesRead(); 10 | //double GetKbps(); 11 | //DateTime GetStartTime(); 12 | /// 13 | /// Gets the metrics for the stream handler. 14 | /// 15 | [XmlIgnore] 16 | StreamHandlerMetrics Metrics { get; } 17 | } -------------------------------------------------------------------------------- /src/StreamMaster.Streams.Domain/Interfaces/IStreamStatus.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Domain.Models; 2 | using StreamMaster.PlayList.Models; 3 | 4 | namespace StreamMaster.Streams.Domain.Interfaces; 5 | 6 | public interface IStreamStatus : IIntroStatus, ISourceName 7 | { 8 | SMChannelDto SMChannel { get; } 9 | CustomPlayList? CustomPlayList { get; set; } 10 | bool Shutdown { get; set; } 11 | bool FailoverInProgress { get; set; } 12 | void SetSMStreamInfo(SMStreamInfo? idNameUrl); 13 | SMStreamInfo? SMStreamInfo { get; } 14 | int StreamGroupProfileId { get; } 15 | } 16 | -------------------------------------------------------------------------------- /src/StreamMaster.Streams.Domain/Interfaces/IVideoCombiner.cs: -------------------------------------------------------------------------------- 1 | using StreamMaster.Streams.Domain.Events; 2 | 3 | namespace StreamMaster.Streams.Domain.Interfaces 4 | { 5 | public interface IVideoCombiner 6 | { 7 | int Id { get; } 8 | event EventHandler? OnVideoCombinerStoppedEvent; 9 | Task CombineVideosAsync(int SMChannelId1, int SMChannelId2, int SMChannelId3, int SMChannelId4, CancellationToken cancellationToken); 10 | } 11 | } -------------------------------------------------------------------------------- /src/StreamMaster.Streams.Domain/Interfaces/StreamResult.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Streams.Domain.Interfaces; 2 | public class StreamResult 3 | { 4 | public IClientConfiguration? ClientConfiguration { get; set; } 5 | public string? RedirectUrl { get; set; } 6 | // Signal when streaming is complete 7 | } 8 | -------------------------------------------------------------------------------- /src/StreamMaster.Streams.Domain/Metrics/StreamConnectionMetric.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Streams.Domain.Metrics; 2 | 3 | public class StreamConnectionMetricData(string? StreamUrl = null) 4 | { 5 | public DateTime? LastSuccessConnectTime { get; set; } 6 | public DateTime? LastErrorTime { get; set; } 7 | public DateTime? LastConnectionAttemptTime { get; set; } 8 | public DateTime LastStartTime { get; set; } = DateTime.UtcNow; 9 | 10 | public int RetryCount { get; set; } 11 | public int TotalConnectionAttempts { get; set; } = 0; 12 | public string StreamUrl { get; } = StreamUrl ?? string.Empty; 13 | } -------------------------------------------------------------------------------- /src/StreamMaster.Streams.Domain/Models/GetStreamResult.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Streams.Domain.Models; 2 | /// 3 | /// Represents the result of a stream creation operation. 4 | /// 5 | /// Gets or sets the created stream, if successful. 6 | /// Gets or sets the process ID associated with the stream. 7 | /// Gets or sets the error information, if applicable. 8 | public record GetStreamResult(Stream? Stream, int ProcessId, ProxyStreamError? Error); 9 | -------------------------------------------------------------------------------- /src/StreamMaster.Streams.Domain/Models/ProxyStreamError.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Streams.Domain.Models; 2 | 3 | public class ProxyStreamError 4 | { 5 | public ProxyStreamErrorCode ErrorCode { get; set; } 6 | public string? Message { get; set; } 7 | } 8 | -------------------------------------------------------------------------------- /src/StreamMaster.Streams/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using Microsoft.Extensions.Logging; 2 | global using Microsoft.Extensions.Options; 3 | 4 | global using StreamMaster.Application.Interfaces; 5 | global using StreamMaster.Domain.Common; 6 | global using StreamMaster.Domain.Configuration; 7 | global using StreamMaster.Domain.Dto; 8 | global using StreamMaster.Domain.Models; 9 | global using StreamMaster.Domain.Repository; 10 | global using StreamMaster.Domain.Services; 11 | global using StreamMaster.PlayList; 12 | 13 | global using StreamMaster.Streams.Domain.Interfaces; 14 | global using StreamMaster.Streams.Domain.Models; -------------------------------------------------------------------------------- /src/StreamMaster.Streams/Plugins/VideoInfoEventArgs.cs: -------------------------------------------------------------------------------- 1 | namespace StreamMaster.Streams.Plugins; 2 | 3 | /// 4 | /// Event arguments for video info updates. 5 | /// 6 | public class VideoInfoEventArgs(VideoInfo videoInfo, string id) : EventArgs 7 | { 8 | /// 9 | /// The updated video information. 10 | /// 11 | public VideoInfo VideoInfo { get; } = videoInfo; 12 | 13 | /// 14 | /// The unique identifier for the video source. 15 | /// 16 | public string Id { get; } = id; 17 | } 18 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "StreamMaster", 3 | "projectOwner": "carlreid", 4 | "repoType": "github", 5 | "repoHost": "https://github.com", 6 | "files": ["../../README.md"], 7 | "imageSize": 100, 8 | "commit": true, 9 | "commitConvention": "angular", 10 | "contributors": [], 11 | "contributorsPerLine": 7, 12 | "linkToUsage": true 13 | } 14 | 15 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/.dockerignore: -------------------------------------------------------------------------------- 1 | **/.classpath 2 | **/.dockerignore 3 | **/.env 4 | **/.git 5 | **/.gitignore 6 | **/.project 7 | **/.settings 8 | **/.toolstarget 9 | **/.vs 10 | **/.vscode 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/charts 15 | **/docker-compose* 16 | **/compose* 17 | **/Dockerfile* 18 | **/node_modules 19 | **/npm-debug.log 20 | **/obj 21 | **/secrets.dev.yaml 22 | **/values.dev.yaml 23 | **/.eslintrc.json 24 | LICENSE 25 | README.md 26 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/.estlintignore: -------------------------------------------------------------------------------- 1 | .eslintrc.json 2 | node_modules 3 | **/.next/** 4 | **/_next/** 5 | **/.vscode/** 6 | **/dist/** 7 | **/styles/** 8 | **/*.css 9 | vite.config.ts 10 | iptvApi.ts 11 | package.json -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/.hintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "development" 4 | ], 5 | "hints": { 6 | "no-inline-styles": "off" 7 | } 8 | } -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/.prettierignore: -------------------------------------------------------------------------------- 1 | # Build artifacts 2 | .next/ 3 | .turbo/ 4 | _next/ 5 | __tmp__/ 6 | build/ 7 | node_modules/ 8 | dist/ -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 160, 3 | "singleQuote": true, 4 | "semi": true, 5 | "trailingComma": "none" 6 | } 7 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"] 3 | } 4 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/app/editor/files/page.tsx: -------------------------------------------------------------------------------- 1 | import FilesEditor from '@features/filesEditor/FilesEditor'; 2 | 3 | export default function FilesEditorLayout() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/app/editor/playlist/page.tsx: -------------------------------------------------------------------------------- 1 | import PlayListEditor from '@features/playListEditor/PlayListEditor'; 2 | 3 | export default function PlayListEditorLayout() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/app/editor/sd/page.tsx: -------------------------------------------------------------------------------- 1 | import SDEditorHeadEndsAndLineUps from '@features/sdEditor/SDEditorHeadEndsAndLineUps'; 2 | 3 | export default function SDEditorLayout() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/app/editor/streamgroup/page.tsx: -------------------------------------------------------------------------------- 1 | import StreamGroupEditor from '@features/streamGroupEditor/StreamGroupEditor'; 2 | 3 | export default function StreamGroupEditorLayout() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/app/editor/streams/page.tsx: -------------------------------------------------------------------------------- 1 | import StreamEditor from '@features/streameditor/StreamEditor'; 2 | 3 | export default function SMStreamEditorLayout() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/app/settings/page.tsx: -------------------------------------------------------------------------------- 1 | import SettingsEditor from '@features/settings/SettingsEditor'; 2 | 3 | export default function SettingsLayout() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/app/streamingstatus/page.tsx: -------------------------------------------------------------------------------- 1 | import StreamingStatus from '@features/streamingStatus/StreamingStatus'; 2 | 3 | export default function StreamingStatusLayout() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/app/testing/page.tsx: -------------------------------------------------------------------------------- 1 | import SMLoader from '@components/loader/SMLoader'; 2 | 3 | export default function StreamGroupSelectedVideoStreamDataSelectorLayout() { 4 | const id = 'streamgroupeditor'; 5 | return ; 6 | } 7 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/app/viewer/logviewer/page.tsx: -------------------------------------------------------------------------------- 1 | import LogViewer from '@features/logViewer/LogViewer'; 2 | 3 | export default function LogViewerLayout() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/app/viewer/player/page.tsx: -------------------------------------------------------------------------------- 1 | import VideoPlayer from '@features/videoPlayer/VideoPlayer'; 2 | 3 | export default function PlayerLayout() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", 3 | "vcs": { 4 | "enabled": false, 5 | "clientKind": "git", 6 | "useIgnoreFile": false 7 | }, 8 | "files": { 9 | "ignoreUnknown": false, 10 | "ignore": [] 11 | }, 12 | "formatter": { 13 | "enabled": true, 14 | "indentStyle": "tab" 15 | }, 16 | "organizeImports": { 17 | "enabled": true 18 | }, 19 | "linter": { 20 | "enabled": true, 21 | "rules": { 22 | "recommended": true 23 | } 24 | }, 25 | "javascript": { 26 | "formatter": { 27 | "quoteStyle": "double" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/components/buttons/AutoSetButton.tsx: -------------------------------------------------------------------------------- 1 | import SMButton from '@components/sm/SMButton'; 2 | import { ChildButtonProperties } from './ChildButtonProperties'; 3 | 4 | const AutoSetButton: React.FC = ({ buttonDisabled = true, onClick, tooltip = 'Auto Set' }) => ( 5 | 6 | ); 7 | 8 | export default AutoSetButton; 9 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/components/buttons/BanButton.tsx: -------------------------------------------------------------------------------- 1 | import SMButton from '@components/sm/SMButton'; 2 | import { ChildButtonProperties } from './ChildButtonProperties'; 3 | 4 | const BanButton: React.FC = ({ buttonClassName, buttonDisabled = false, onClick, tooltip = '' }) => ( 5 | 6 | ); 7 | 8 | export default BanButton; 9 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/components/buttons/BookButton.tsx: -------------------------------------------------------------------------------- 1 | import SMButton from '@components/sm/SMButton'; 2 | import { ChildButtonProperties } from './ChildButtonProperties'; 3 | 4 | const BookButton: React.FC = ({ buttonDisabled = false, iconFilled = true, label, onClick, tooltip = '' }) => ( 5 | 6 | ); 7 | 8 | export default BookButton; 9 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/components/buttons/ChildButtonProperties.ts: -------------------------------------------------------------------------------- 1 | import { SyntheticEvent } from 'react'; 2 | 3 | export interface ChildButtonProperties { 4 | buttonClassName?: string; 5 | buttonDisabled?: boolean; 6 | iconFilled?: boolean; 7 | isLeft?: boolean; 8 | label?: string; 9 | onClick?: (e: SyntheticEvent) => void; 10 | style?: React.CSSProperties; 11 | tooltip?: string; 12 | outlined?: boolean; 13 | } 14 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/components/buttons/ClearButton.tsx: -------------------------------------------------------------------------------- 1 | import SMButton from '@components/sm/SMButton'; 2 | import { ChildButtonProperties } from './ChildButtonProperties'; 3 | 4 | const ClearButton: React.FC = ({ buttonDisabled = true, onClick, tooltip = '' }) => ( 5 | 6 | ); 7 | 8 | export default ClearButton; 9 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/components/buttons/ClockButton.tsx: -------------------------------------------------------------------------------- 1 | import SMButton from '@components/sm/SMButton'; 2 | import { ChildButtonProperties } from './ChildButtonProperties'; 3 | 4 | const ClockButton: React.FC = ({ buttonDisabled = false, label, onClick, tooltip = 'Time Shift', iconFilled }) => ( 5 | 6 | ); 7 | 8 | export default ClockButton; 9 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/components/buttons/CloseButton.tsx: -------------------------------------------------------------------------------- 1 | import SMButton from '@components/sm/SMButton'; 2 | import { ChildButtonProperties } from './ChildButtonProperties'; 3 | 4 | const CloseButton: React.FC = ({ onClick }) => { 5 | // return ; 6 | return ; 7 | }; 8 | 9 | export default CloseButton; 10 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/components/buttons/EditButton.tsx: -------------------------------------------------------------------------------- 1 | import SMButton from '@components/sm/SMButton'; 2 | import { ChildButtonProperties } from './ChildButtonProperties'; 3 | 4 | const EditButton: React.FC = ({ buttonDisabled = false, iconFilled, label, onClick, tooltip = 'Edit' }) => ( 5 | 13 | ); 14 | 15 | export default EditButton; 16 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/components/buttons/GoButton.tsx: -------------------------------------------------------------------------------- 1 | import SMButton from '@components/sm/SMButton'; 2 | import { ChildButtonProperties } from './ChildButtonProperties'; 3 | 4 | const GoButton: React.FC = ({ disabled = false, onClick, tooltip = 'Remove', iconFilled, label }) => ( 5 | 6 | ); 7 | 8 | export default GoButton; 9 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/components/buttons/ImageButton.tsx: -------------------------------------------------------------------------------- 1 | import SMButton from '@components/sm/SMButton'; 2 | import { ChildButtonProperties } from './ChildButtonProperties'; 3 | 4 | const ImageButton: React.FC = ({ disabled = true, iconFilled = true, onClick, tooltip = '' }) => ( 5 | 6 | ); 7 | 8 | export default ImageButton; 9 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/components/buttons/LeftArrowButton.tsx: -------------------------------------------------------------------------------- 1 | import SMButton from '@components/sm/SMButton'; 2 | import { ChildButtonProperties } from './ChildButtonProperties'; 3 | 4 | const LeftArrowButton: React.FC = ({ disabled = false, onClick, tooltip = 'Add' }) => ( 5 | 6 | ); 7 | 8 | export default LeftArrowButton; 9 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/components/buttons/MaximizeButton.tsx: -------------------------------------------------------------------------------- 1 | import SMButton from '@components/sm/SMButton'; 2 | import { ChildButtonProperties } from './ChildButtonProperties'; 3 | 4 | const MaximizeButton: React.FC = ({ iconFilled = true, onClick, tooltip = '' }) => ( 5 | 14 | ); 15 | 16 | export default MaximizeButton; 17 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/components/buttons/MinusButton.tsx: -------------------------------------------------------------------------------- 1 | import SMButton from '@components/sm/SMButton'; 2 | import { ChildButtonProperties } from './ChildButtonProperties'; 3 | 4 | const MinusButton: React.FC = ({ buttonDisabled = false, iconFilled, label, onClick, tooltip = 'Delete Stream' }) => { 5 | return ; 6 | }; 7 | 8 | export default MinusButton; 9 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/components/buttons/RefreshButton.tsx: -------------------------------------------------------------------------------- 1 | import SMButton from '@components/sm/SMButton'; 2 | import { ChildButtonProperties } from './ChildButtonProperties'; 3 | 4 | const RefreshButton: React.FC = ({ buttonDisabled = false, onClick, tooltip = '' }) => ( 5 | 6 | ); 7 | 8 | export default RefreshButton; 9 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/components/buttons/RightArrowButton.tsx: -------------------------------------------------------------------------------- 1 | import SMButton from '@components/sm/SMButton'; 2 | import { ChildButtonProperties } from './ChildButtonProperties'; 3 | 4 | const RightArrowButton: React.FC = ({ buttonDisabled = false, onClick, tooltip = 'Add' }) => ( 5 | 6 | ); 7 | 8 | export default RightArrowButton; 9 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/components/buttons/SGAddButton.tsx: -------------------------------------------------------------------------------- 1 | import SMButton from '@components/sm/SMButton'; 2 | import { ChildButtonProperties } from './ChildButtonProperties'; 3 | 4 | const SGAddButton: React.FC = ({ buttonDisabled, onClick, tooltip }) => { 5 | return ; 6 | }; 7 | 8 | export default SGAddButton; 9 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/components/buttons/SGRemoveButton.tsx: -------------------------------------------------------------------------------- 1 | import SMButton from '@components/sm/SMButton'; 2 | import { ChildButtonProperties } from './ChildButtonProperties'; 3 | 4 | const SGRemoveButton: React.FC = ({ onClick, buttonDisabled, tooltip }) => { 5 | return ; 6 | }; 7 | 8 | export default SGRemoveButton; 9 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/components/buttons/SearchButton.tsx: -------------------------------------------------------------------------------- 1 | import SMButton from '@components/sm/SMButton'; 2 | import { ChildButtonProperties } from './ChildButtonProperties'; 3 | 4 | const SearchButton: React.FC = ({ buttonDisabled = false, onClick, tooltip = 'Add' }) => ( 5 | 6 | ); 7 | 8 | export default SearchButton; 9 | -------------------------------------------------------------------------------- /src/StreamMaster.WebUI/components/buttons/SunButton.tsx: -------------------------------------------------------------------------------- 1 | import { getRightToolOptions } from '@lib/common/common'; 2 | import { Button } from 'primereact/button'; 3 | import { ChildButtonProperties } from './ChildButtonProperties'; 4 | 5 | interface SunButtonProperties extends ChildButtonProperties { 6 | isDark: boolean; 7 | } 8 | 9 | const SunButton: React.FC = ({ onClick, isDark }) => ( 10 |