├── .all-contributorsrc ├── .bettercodehub.yml ├── .dockerignore ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── Bug_report.md │ └── Feature_request.md ├── dco.yml ├── dependabot.yml ├── labeler.yml └── workflows │ ├── label.yml │ ├── new-translations.yml │ └── no-response.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── EmbyStat.Clients.Base ├── Api │ └── IMediaServerApi.cs ├── ClientStrategy.cs ├── EmbyStat.Clients.Base.csproj ├── Http │ ├── BaseHttpClient.cs │ ├── IBaseHttpClient.cs │ ├── IRefitHttpClientFactory.cs │ ├── RefitHttpClientFactory.cs │ └── ServerSearcher.cs ├── IClientFactory.cs ├── IClientStrategy.cs ├── IMetadataClientFactory.cs ├── Metadata │ └── IMetadataClient.cs └── WebSocket │ ├── IWebSocketApi.cs │ ├── IWebSocketClient.cs │ └── WebSocketApi.cs ├── EmbyStat.Clients.Emby ├── EmbyClientFactory.cs ├── EmbyStat.Clients.Emby.csproj ├── Http │ ├── EmbyBaseHttpClient.cs │ └── IEmbyBaseHttpClient.cs └── WebSocket │ ├── EmbyWebSocketClient.cs │ └── IEmbyWebSocketClient.cs ├── EmbyStat.Clients.GitHub ├── EmbyStat.Clients.GitHub.csproj ├── GitHubClient.cs ├── IGitHubApi.cs ├── IGitHubClient.cs └── Models │ ├── Asset.cs │ ├── Author.cs │ ├── PackageInfo.cs │ ├── ReleaseObject.cs │ └── UpdateResult.cs ├── EmbyStat.Clients.Jellyfin ├── EmbyStat.Clients.Jellyfin.csproj ├── Http │ ├── IJellyfinBaseHttpClient.cs │ └── JellyfinBaseHttpClient.cs ├── JellyfinClientFactory.cs └── WebSocket │ └── IJellyfinWebSocketClient.cs ├── EmbyStat.Clients.Tmdb ├── EmbyStat.Clients.Tmdb.csproj ├── ITmdbClient.cs ├── TmdbClient.cs └── TmdbClientFactory.cs ├── EmbyStat.Clients.TvMaze ├── EmbyStat.Clients.TvMaze.csproj ├── ITvMazeShowClient.cs ├── TvMazeClientFactory.cs └── TvMazeShowClient.cs ├── EmbyStat.Common ├── ChartGrouping.cs ├── Constants.cs ├── Converters │ ├── SessionConverter.cs │ └── TopCardHelper.cs ├── EmbyStat.Common.csproj ├── Enums │ ├── CardType.cs │ ├── ImageType.cs │ ├── LibraryType.cs │ ├── LocationType.cs │ ├── MediaProtocol.cs │ ├── MediaStreamType.cs │ ├── MediaType.cs │ ├── MetadataServerType.cs │ ├── PersonType.cs │ ├── PlayMethod.cs │ ├── RepeatMode.cs │ ├── ServerType.cs │ ├── StatisticType.cs │ ├── TranscodeReason.cs │ ├── UpdateLevel.cs │ ├── UpdateTrain.cs │ └── Video3DFormat.cs ├── Exceptions │ ├── ApiError.cs │ ├── BusinessException.cs │ ├── BusinessExceptionFilterAttribute.cs │ ├── EmbyStatStartupException.cs │ ├── NotFoundException.cs │ └── WizardNotFinishedException.cs ├── Extensions │ ├── DictionaryExtensions.cs │ ├── DoubleExtensions.cs │ ├── IntExtensions.cs │ ├── ItemQueryExtensions.cs │ ├── LibrarySyncTypeExtensions.cs │ ├── ListExtensions.cs │ ├── MediaExtensions.cs │ ├── MediaServerExtensions.cs │ ├── MovieExtensions.cs │ ├── RoundNumberExtension.cs │ ├── ShowExtensions.cs │ ├── StringExtensions.cs │ └── VirtualEpisodeExtensions.cs ├── Generators │ └── KeyGenerator.cs ├── Helpers │ └── ListContainer.cs └── Models │ ├── Account │ ├── AccessToken.cs │ ├── AuthenticateRequest.cs │ ├── AuthenticateResponse.cs │ ├── ChangePasswordRequest.cs │ ├── ChangeUserNameRequest.cs │ └── RefreshTokenRequest.cs │ ├── Cards │ ├── Card.cs │ └── TopCard.cs │ ├── Charts │ ├── Chart.cs │ └── SimpleChartData.cs │ ├── DataGrid │ └── Page.cs │ ├── Entities │ ├── Device.cs │ ├── EmbyStatUser.cs │ ├── Events │ │ ├── Play.cs │ │ ├── PlayState.cs │ │ └── Session.cs │ ├── FilterValues.cs │ ├── Genre.cs │ ├── Helpers │ │ ├── Extra.cs │ │ ├── ILinkedMedia.cs │ │ ├── LabelValuePair.cs │ │ ├── Media.cs │ │ ├── MediaPerson.cs │ │ ├── RefreshToken.cs │ │ └── Video.cs │ ├── Job.cs │ ├── Language.cs │ ├── Library.cs │ ├── LibrarySyncType.cs │ ├── MediaServerInfo.cs │ ├── MediaServerStatus.cs │ ├── MediaServerUserView.cs │ ├── Movies │ │ └── Movie.cs │ ├── Person.cs │ ├── PluginInfo.cs │ ├── Shows │ │ ├── Episode.cs │ │ ├── Season.cs │ │ └── Show.cs │ ├── Statistic.cs │ ├── Streams │ │ ├── AudioStream.cs │ │ ├── MediaSource.cs │ │ ├── SubtitleStream.cs │ │ └── VideoStream.cs │ └── Users │ │ └── MediaServerUser.cs │ ├── GenericEventArgs.cs │ ├── ItemQuery.cs │ ├── MediaServer │ ├── MediaServerUserRow.cs │ └── UserMediaView.cs │ ├── MediaServerUdpBroadcast.cs │ ├── Net │ ├── BaseItemDto.cs │ ├── BaseItemPerson.cs │ ├── BaseMediaSourceInfo.cs │ ├── BaseMediaStream.cs │ ├── BaseUserDto.cs │ └── UserData.cs │ ├── OptionSerializerAttribute.cs │ ├── Query │ └── Filter.cs │ ├── Show │ └── VirtualEpisode.cs │ ├── StartupOptions.cs │ ├── Tasks │ ├── Enum │ │ ├── JobState.cs │ │ └── ProgressLogType.cs │ ├── JobLog.cs │ └── JobProgress.cs │ └── WebSocketMessage.cs ├── EmbyStat.Configuration ├── Config.cs ├── ConfigurationService.cs ├── EmbyStat.Configuration.csproj ├── Interfaces │ └── IConfigurationService.cs └── InvalidConfigFileException.cs ├── EmbyStat.Controllers ├── About │ ├── AboutController.cs │ └── AboutViewModel.cs ├── Account │ └── AccountController.cs ├── EmbyStat.Controllers.csproj ├── Filters │ ├── FilterController.cs │ └── FilterValuesViewModel.cs ├── HelperClasses │ ├── ActiveFilterViewModel.cs │ ├── CardViewModel.cs │ ├── ChartViewModel.cs │ ├── LabelValuePairViewModel.cs │ ├── LibraryViewModel.cs │ ├── PageViewModel.cs │ ├── Streams │ │ ├── AudioStreamViewModel.cs │ │ ├── MediaSourceViewModel.cs │ │ ├── MoviePersonViewModel.cs │ │ ├── SubtitleStreamViewModel.cs │ │ └── VideoStreamViewModel.cs │ ├── TopCardViewModel.cs │ └── UserMediaViewViewModel.cs ├── Job │ ├── JobController.cs │ └── JobViewModel.cs ├── Log │ ├── LogController.cs │ └── LogFileViewModel.cs ├── MapProfiles.cs ├── MediaServer │ ├── LoginViewModel.cs │ ├── MediaServerController.cs │ ├── MediaServerLibraryViewModel.cs │ ├── MediaServerUserRowViewModel.cs │ ├── MediaServerUserStatisticsViewModel.cs │ ├── PluginViewModel.cs │ ├── ServerInfoViewModel.cs │ ├── StatusViewModel.cs │ ├── UdpBroadcastViewModel.cs │ ├── UrlViewModel.cs │ ├── UserFullViewModel.cs │ ├── UserIdViewModel.cs │ └── UserOverviewViewModel.cs ├── Middleware │ └── RequestLoggingMiddleware.cs ├── Movie │ ├── MovieController.cs │ ├── MovieRowViewModel.cs │ ├── MovieStatisticsViewModel.cs │ ├── MovieViewModel.cs │ ├── ShortMovieViewModel.cs │ ├── SuspiciousMovieViewModel.cs │ └── SuspiciousTablesViewModel.cs ├── Settings │ ├── ConfigViewModel.cs │ ├── LanguageViewModel.cs │ └── SettingsController.cs ├── Show │ ├── ShowChartsViewModel.cs │ ├── ShowController.cs │ ├── ShowDetailViewModel.cs │ ├── ShowRowViewModel.cs │ ├── ShowStatisticsViewModel.cs │ └── VirtualEpisodeViewModel.cs └── System │ ├── SystemController.cs │ └── UpdateResultViewModel.cs ├── EmbyStat.Core ├── About │ ├── AboutModel.cs │ ├── AboutService.cs │ └── Interfaces │ │ └── IAboutService.cs ├── Abstract │ ├── MediaService.cs │ └── StatisticHelper.cs ├── Account │ ├── AccountService.cs │ └── Interfaces │ │ └── IAccountService.cs ├── Authentication │ └── AuthenticationHelper.cs ├── DataStore │ ├── EsDbContext.cs │ ├── ISqliteBootstrap.cs │ ├── Migrations │ │ └── Sqlite │ │ │ ├── 20220622095519_Init.Designer.cs │ │ │ ├── 20220622095519_Init.cs │ │ │ ├── 20220711095301_SyncTypeAdded.Designer.cs │ │ │ ├── 20220711095301_SyncTypeAdded.cs │ │ │ ├── 20220712101203_MovedSyncTypeTable.Designer.cs │ │ │ ├── 20220712101203_MovedSyncTypeTable.cs │ │ │ ├── 20220712221112_MovedSyncDateTimeToLibrarySyncTypes.Designer.cs │ │ │ ├── 20220712221112_MovedSyncDateTimeToLibrarySyncTypes.cs │ │ │ └── EsDbContextModelSnapshot.cs │ ├── Seeds │ │ ├── JobSeed.cs │ │ ├── LanguageSeed.cs │ │ └── MediaServerSeed.cs │ └── SqliteBootstrap.cs ├── Disk │ ├── DiskProvider.cs │ └── Interfaces │ │ └── IDiskProvider.cs ├── EmbyStat.Core.csproj ├── EnvironmentInfo │ ├── Interfaces │ │ ├── IOsInfo.cs │ │ └── IOsVersionAdapter.cs │ ├── OsInfo.cs │ ├── OsVersionAdapters │ │ ├── FreebsdVersionAdapter.cs │ │ ├── MacOsVersionAdapter.cs │ │ ├── ReleaseFileVersionAdapter.cs │ │ └── WindowsVersionInfo.cs │ └── OsVersionModel.cs ├── Filters │ ├── FilterRepository.cs │ ├── FilterService.cs │ └── Interfaces │ │ ├── IFilterRepository.cs │ │ └── IFilterService.cs ├── Genres │ ├── GenreRepository.cs │ └── Interfaces │ │ └── IGenreRepository.cs ├── Hubs │ ├── EmbyStatHub.cs │ ├── HubHelper.cs │ └── IHubHelper.cs ├── Jobs │ ├── Interfaces │ │ ├── IJobRepository.cs │ │ └── IJobService.cs │ ├── JobRepository.cs │ └── JobService.cs ├── Languages │ ├── Interfaces │ │ ├── ILanguageRepository.cs │ │ └── ILanguageService.cs │ ├── LanguageRepository.cs │ └── LanguageService.cs ├── Logging │ ├── Interfaces │ │ └── ILogsService.cs │ ├── LogFile.cs │ └── LogService.cs ├── MediaHelpers │ └── Interfaces │ │ └── IMediaRepository.cs ├── MediaServers │ ├── Interfaces │ │ ├── IMediaServerRepository.cs │ │ └── IMediaServerService.cs │ ├── MediaServerRepository.cs │ ├── MediaServerService.cs │ └── MediaServerUserStatistics.cs ├── Movies │ ├── Interfaces │ │ ├── IMovieRepository.cs │ │ └── IMovieService.cs │ ├── MovieRepository.cs │ ├── MovieService.cs │ ├── MovieStatistics.cs │ ├── ShortMovie.cs │ ├── SuspiciousMovie.cs │ └── SuspiciousTables.cs ├── People │ ├── Interfaces │ │ └── IPersonRepository.cs │ └── PersonRepository.cs ├── Processes │ ├── Interfaces │ │ └── IProcessProvider.cs │ ├── ProcessOutput.cs │ ├── ProcessOutputLevel.cs │ ├── ProcessOutputLine.cs │ └── ProcessProvider.cs ├── Sessions │ ├── Interfaces │ │ ├── ISessionRepository.cs │ │ └── ISessionService.cs │ └── SessionService.cs ├── Shows │ ├── Interfaces │ │ ├── IShowRepository.cs │ │ └── IShowService.cs │ ├── ShowCharts.cs │ ├── ShowRepository.cs │ ├── ShowService.cs │ └── ShowStatistics.cs ├── Statistics │ ├── Interfaces │ │ └── IStatisticsRepository.cs │ └── StatisticsRepository.cs ├── System │ ├── Interfaces │ │ └── ISystemService.cs │ └── SystemService.cs ├── Updates │ ├── Interfaces │ │ └── IUpdateService.cs │ └── UpdateService.cs └── WebSockets │ ├── Interfaces │ └── IWebSocketService.cs │ └── WebSocketService.cs ├── EmbyStat.DI ├── DiExtensions.cs └── EmbyStat.DI.csproj ├── EmbyStat.Hosts.Cmd ├── ApplicationModes.cs ├── DefaultConfig.cs ├── EmbyStat.Hosts.Cmd.csproj ├── Program.cs └── Startup.cs ├── EmbyStat.Jobs ├── BaseJob.cs ├── EmbyStat.Jobs.csproj ├── IBaseJob.cs ├── IJobInitializer.cs ├── JobInitializer.cs └── Jobs │ ├── Interfaces │ ├── ICheckUpdateJob.cs │ ├── IDatabaseCleanupJob.cs │ ├── IMovieSyncJob.cs │ ├── IPingEmbyJob.cs │ ├── IShowSyncJob.cs │ └── ISmallSyncJob.cs │ ├── Maintenance │ ├── DatabaseCleanupJob.cs │ └── PingEmbyJob.cs │ ├── Sync │ ├── MovieSyncJob.cs │ ├── ShowSyncJob.cs │ └── SmallSyncJob.cs │ └── Updater │ └── CheckUpdateJob.cs ├── EmbyStat.Migrator ├── EmbyStat.Migrator.csproj ├── Interfaces │ ├── IMigration.cs │ ├── IMigrationRunner.cs │ └── IMigrationSourceItem.cs ├── MigrationRunner.cs ├── Migrations │ └── 0001_CreateUserSettings.cs ├── Models │ ├── AssemblyMigrationSourceItem.cs │ ├── Migration.cs │ └── version.cs └── ServiceCollectionMigratorExtention.cs ├── EmbyStat.Web ├── .config │ └── dotnet-tools.json ├── ClientApp │ ├── .eslintrc.yml │ ├── .gitignore │ ├── .vscode │ │ └── settings.json │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── locales │ │ │ ├── base.json │ │ │ ├── da-DK.json │ │ │ ├── de-DE.json │ │ │ ├── el-GR.json │ │ │ ├── en-US.json │ │ │ ├── es-ES.json │ │ │ ├── fi-FI.json │ │ │ ├── fr-FR.json │ │ │ ├── hu-HU.json │ │ │ ├── it-IT.json │ │ │ ├── nl-NL.json │ │ │ ├── no-NO.json │ │ │ ├── pl-PL.json │ │ │ ├── pt-BR.json │ │ │ ├── pt-PT.json │ │ │ ├── ro-RO.json │ │ │ ├── sv-SE.json │ │ │ └── zh-CN.json │ │ ├── manifest.json │ │ ├── robots.txt │ │ └── runtime-config.js │ ├── src │ │ ├── App.tsx │ │ ├── authentication │ │ │ ├── index.tsx │ │ │ └── requireAuth.tsx │ │ ├── i18n.tsx │ │ ├── index.css │ │ ├── index.tsx │ │ ├── pages │ │ │ ├── about │ │ │ │ ├── About.tsx │ │ │ │ ├── hooks │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── useAbout.tsx │ │ │ │ └── index.tsx │ │ │ ├── home │ │ │ │ ├── home.tsx │ │ │ │ └── index.tsx │ │ │ ├── jobs │ │ │ │ ├── JobItem.tsx │ │ │ │ ├── JobList.tsx │ │ │ │ ├── JobLogs.tsx │ │ │ │ ├── JobSettingsDialog.tsx │ │ │ │ ├── Jobs.tsx │ │ │ │ └── index.tsx │ │ │ ├── login │ │ │ │ ├── Login.tsx │ │ │ │ ├── LoginForm.tsx │ │ │ │ ├── RecoverPasswordForm.tsx │ │ │ │ └── index.tsx │ │ │ ├── logs │ │ │ │ ├── Logs.tsx │ │ │ │ └── index.tsx │ │ │ ├── movies │ │ │ │ ├── General.tsx │ │ │ │ ├── List.tsx │ │ │ │ ├── MovieFilters.tsx │ │ │ │ ├── Movies.tsx │ │ │ │ ├── Table │ │ │ │ │ ├── Helpers │ │ │ │ │ │ ├── Body.tsx │ │ │ │ │ │ ├── DataLine.tsx │ │ │ │ │ │ ├── MultiString.tsx │ │ │ │ │ │ ├── Row.tsx │ │ │ │ │ │ ├── StreamLists.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── MovieDetailRow.tsx │ │ │ │ │ ├── Table.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── useMovieTable.tsx │ │ │ │ └── index.tsx │ │ │ ├── server │ │ │ │ ├── Server.tsx │ │ │ │ ├── ServerInfo.tsx │ │ │ │ ├── ServerPlugins.tsx │ │ │ │ ├── components │ │ │ │ │ ├── EsServerDetails.tsx │ │ │ │ │ ├── EsServerExtraInfo.tsx │ │ │ │ │ ├── EsServerFeatures.tsx │ │ │ │ │ ├── EsServerPaths.tsx │ │ │ │ │ └── index.tsx │ │ │ │ └── index.tsx │ │ │ ├── settings │ │ │ │ ├── Movies.tsx │ │ │ │ ├── Server.tsx │ │ │ │ ├── Settings.tsx │ │ │ │ ├── Shows.tsx │ │ │ │ ├── components │ │ │ │ │ ├── EsLanguageCard.tsx │ │ │ │ │ ├── EsMediaServerCard.tsx │ │ │ │ │ ├── EsPasswordCard.tsx │ │ │ │ │ ├── EsRollbarCard.tsx │ │ │ │ │ ├── EsTmdbApiCard.tsx │ │ │ │ │ ├── EsUserCard.tsx │ │ │ │ │ └── index.tsx │ │ │ │ └── index.tsx │ │ │ ├── shows │ │ │ │ ├── General.tsx │ │ │ │ ├── List.tsx │ │ │ │ ├── ShowFilters.tsx │ │ │ │ ├── Shows.tsx │ │ │ │ ├── Table │ │ │ │ │ ├── Body.tsx │ │ │ │ │ ├── EpisodeColumn.tsx │ │ │ │ │ ├── MissingEpisodeList.tsx │ │ │ │ │ ├── Row.tsx │ │ │ │ │ ├── ShowDetailRow.tsx │ │ │ │ │ ├── Table.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── useShowTable.tsx │ │ │ │ └── index.tsx │ │ │ ├── users │ │ │ │ ├── Users.tsx │ │ │ │ ├── components │ │ │ │ │ ├── EsUserStatistics.tsx │ │ │ │ │ ├── EsUserTable.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── hooks │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── useUserDetails.tsx │ │ │ │ │ └── useUserTable.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── subpages │ │ │ │ │ ├── UserDetails.tsx │ │ │ │ │ ├── components │ │ │ │ │ ├── Header.tsx │ │ │ │ │ ├── User.tsx │ │ │ │ │ └── index.tsx │ │ │ │ │ └── index.tsx │ │ │ └── wizard │ │ │ │ ├── Interfaces.tsx │ │ │ │ ├── Steps │ │ │ │ ├── ConfigureLibrary.tsx │ │ │ │ ├── Finish.tsx │ │ │ │ ├── Helpers │ │ │ │ │ ├── NewServerCard.tsx │ │ │ │ │ ├── ServerCard.tsx │ │ │ │ │ ├── TestFailed.tsx │ │ │ │ │ ├── TestSuccessFul.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── Intro.tsx │ │ │ │ ├── MediaServerDetails.tsx │ │ │ │ ├── SearchMediaServer.tsx │ │ │ │ ├── TestMediaServer.tsx │ │ │ │ ├── UserDetails.tsx │ │ │ │ └── index.tsx │ │ │ │ ├── Wizard.tsx │ │ │ │ └── index.tsx │ │ ├── react-app-env.d.ts │ │ ├── reportWebVitals.ts │ │ ├── routes.tsx │ │ ├── setupTests.ts │ │ ├── shared │ │ │ ├── assets │ │ │ │ ├── icons │ │ │ │ │ └── flags │ │ │ │ │ │ ├── ara.svg │ │ │ │ │ │ ├── bas.svg │ │ │ │ │ │ ├── bul.svg │ │ │ │ │ │ ├── cat.svg │ │ │ │ │ │ ├── chi.svg │ │ │ │ │ │ ├── cze.svg │ │ │ │ │ │ ├── dan.svg │ │ │ │ │ │ ├── dut.svg │ │ │ │ │ │ ├── eng.svg │ │ │ │ │ │ ├── est.svg │ │ │ │ │ │ ├── fin.svg │ │ │ │ │ │ ├── fre.svg │ │ │ │ │ │ ├── ger.svg │ │ │ │ │ │ ├── gre.svg │ │ │ │ │ │ ├── heb.svg │ │ │ │ │ │ ├── hin.svg │ │ │ │ │ │ ├── hrv.svg │ │ │ │ │ │ ├── hun.svg │ │ │ │ │ │ ├── ice.svg │ │ │ │ │ │ ├── ind.svg │ │ │ │ │ │ ├── ita.svg │ │ │ │ │ │ ├── jpn.svg │ │ │ │ │ │ ├── kor.svg │ │ │ │ │ │ ├── lav.svg │ │ │ │ │ │ ├── lit.svg │ │ │ │ │ │ ├── mac.svg │ │ │ │ │ │ ├── may.svg │ │ │ │ │ │ ├── nor.svg │ │ │ │ │ │ ├── per.svg │ │ │ │ │ │ ├── pol.svg │ │ │ │ │ │ ├── por-bra.svg │ │ │ │ │ │ ├── por.svg │ │ │ │ │ │ ├── rum.svg │ │ │ │ │ │ ├── rus.svg │ │ │ │ │ │ ├── scc.svg │ │ │ │ │ │ ├── slo.svg │ │ │ │ │ │ ├── slv.svg │ │ │ │ │ │ ├── spa.svg │ │ │ │ │ │ ├── srp.svg │ │ │ │ │ │ ├── swa.svg │ │ │ │ │ │ ├── swe.svg │ │ │ │ │ │ ├── tha.svg │ │ │ │ │ │ ├── tur.svg │ │ │ │ │ │ ├── ukr.svg │ │ │ │ │ │ └── vie.svg │ │ │ │ └── images │ │ │ │ │ ├── emby.png │ │ │ │ │ ├── jellyfin.png │ │ │ │ │ ├── logo-small.png │ │ │ │ │ ├── no-poster.png │ │ │ │ │ ├── running-logo.gif │ │ │ │ │ └── under-construction.webp │ │ │ ├── components │ │ │ │ ├── blockers │ │ │ │ │ ├── EsJobRunning.tsx │ │ │ │ │ ├── EsNoMedia.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── buttons │ │ │ │ │ ├── EsButton.tsx │ │ │ │ │ ├── EsHyperLinkButton.tsx │ │ │ │ │ ├── EsRoundIconButton.tsx │ │ │ │ │ ├── EsSaveButton.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── cards │ │ │ │ │ ├── EsBasicCard.tsx │ │ │ │ │ ├── EsSaveCard.tsx │ │ │ │ │ ├── EsTopListCard.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── charts │ │ │ │ │ ├── EsBarGraph.tsx │ │ │ │ │ ├── EsPieChart.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── esAppBar │ │ │ │ │ ├── EsAppBar.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── esAvatar │ │ │ │ │ ├── EsAvatar.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── esBoolCheck │ │ │ │ │ ├── EsBoolCheck.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── esChipList │ │ │ │ │ ├── EsChipList.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── esDateOrNever │ │ │ │ │ ├── EsDateOrNever.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── esFlag │ │ │ │ │ ├── EsFlag.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── esFlagList │ │ │ │ │ ├── EsFlagList.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── esLibrarySelector │ │ │ │ │ ├── EsLibrarySelector.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── esLoading │ │ │ │ │ ├── EsLoading.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── esMenuDrawer │ │ │ │ │ ├── EsMenuDrawer.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── menuItems.tsx │ │ │ │ ├── esPageLoader │ │ │ │ │ ├── EsPageLoader.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── esPoster │ │ │ │ │ ├── EsPoster.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── esScrollbar │ │ │ │ │ ├── EsScrollbar.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── esSortLabel │ │ │ │ │ ├── EsSortLabel.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── esTextInput │ │ │ │ │ ├── esTextInput.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── esTitle │ │ │ │ │ ├── EsChipTitle.tsx │ │ │ │ │ ├── EsTitle.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── filter │ │ │ │ │ ├── EsFilterChip.tsx │ │ │ │ │ ├── EsFilterContainer.tsx │ │ │ │ │ ├── EsFilterInputContainer.tsx │ │ │ │ │ ├── EsFlagMenuItem.tsx │ │ │ │ │ ├── EsNewFilterDialog.tsx │ │ │ │ │ ├── fields │ │ │ │ │ │ ├── EsFilterDropdownField.tsx │ │ │ │ │ │ ├── EsFilterNumberField.tsx │ │ │ │ │ │ ├── EsFilterRangeField.tsx │ │ │ │ │ │ └── EsFilterTextField.tsx │ │ │ │ │ └── index.tsx │ │ │ │ └── table │ │ │ │ │ ├── EsBoolRow.tsx │ │ │ │ │ ├── EsDetailRowSkeleton.tsx │ │ │ │ │ ├── EsFetchFailedRow.tsx │ │ │ │ │ ├── EsTableHeader.tsx │ │ │ │ │ ├── EsTablePagination.tsx │ │ │ │ │ ├── Types.tsx │ │ │ │ │ └── index.tsx │ │ │ ├── context │ │ │ │ ├── ILibraryContext.tsx │ │ │ │ ├── jobs │ │ │ │ │ ├── JobContextProvider.tsx │ │ │ │ │ ├── JobState.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── library │ │ │ │ │ ├── LibrariesContextProvider.tsx │ │ │ │ │ ├── LibrariesState.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── mediaServerUser │ │ │ │ │ ├── MediaServerUserContextProvider.tsx │ │ │ │ │ ├── MediaServerUserState.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── movies │ │ │ │ │ ├── MoviesContextProvider.tsx │ │ │ │ │ ├── MoviesState.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── server │ │ │ │ │ ├── ServerContextProvider.tsx │ │ │ │ │ ├── ServerState.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── settings │ │ │ │ │ ├── SettingsContextProvider.tsx │ │ │ │ │ ├── SettingsState.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── shows │ │ │ │ │ ├── ShowsContextProvider.tsx │ │ │ │ │ ├── ShowsState.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── signalr │ │ │ │ │ ├── SignalRContextProvider.tsx │ │ │ │ │ ├── SignalRState.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── user │ │ │ │ │ ├── UserContextProvider.tsx │ │ │ │ │ ├── UserState.tsx │ │ │ │ │ └── index.tsx │ │ │ │ └── wizard │ │ │ │ │ ├── WizardContextProvider.tsx │ │ │ │ │ └── WizardState.tsx │ │ │ ├── hooks │ │ │ │ ├── index.tsx │ │ │ │ ├── useEsLocation.tsx │ │ │ │ ├── useFilterHelpers.tsx │ │ │ │ ├── useHasAnyAdmins.tsx │ │ │ │ ├── useLocale.tsx │ │ │ │ ├── useMediaServerUrls.tsx │ │ │ │ ├── usePalette.tsx │ │ │ │ ├── useSearchMediaServers.tsx │ │ │ │ ├── useServerType.tsx │ │ │ │ └── useShowDetails.tsx │ │ │ ├── models │ │ │ │ ├── about │ │ │ │ │ ├── About.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── common │ │ │ │ │ ├── Card.tsx │ │ │ │ │ ├── Chart.tsx │ │ │ │ │ ├── Color.tsx │ │ │ │ │ ├── LabelValuePair.tsx │ │ │ │ │ ├── Media.tsx │ │ │ │ │ ├── TablePage.tsx │ │ │ │ │ ├── TopCard.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── filter │ │ │ │ │ ├── ActiveFilter.tsx │ │ │ │ │ ├── FilterConstants.tsx │ │ │ │ │ ├── FilterDefinition.tsx │ │ │ │ │ ├── FilterValues.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── jobs │ │ │ │ │ ├── JobLogLine.tsx │ │ │ │ │ ├── JobProgress.tsx │ │ │ │ │ ├── Jobs.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── language │ │ │ │ │ ├── Language.ts │ │ │ │ │ └── index.tsx │ │ │ │ ├── library │ │ │ │ │ ├── Library.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── login │ │ │ │ │ ├── AuthenticateResponse.tsx │ │ │ │ │ ├── JwtPayloadCustom.tsx │ │ │ │ │ ├── User.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── logs │ │ │ │ │ ├── LogFile.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── mediaServer │ │ │ │ │ ├── MediaServer.tsx │ │ │ │ │ ├── MediaServerInfo.tsx │ │ │ │ │ ├── MediaServerLogin.tsx │ │ │ │ │ ├── MediaServerPlugin.tsx │ │ │ │ │ ├── MediaServerUdpBroadcast.tsx │ │ │ │ │ ├── MediaServerUser.tsx │ │ │ │ │ ├── MediaServerUserRow.tsx │ │ │ │ │ ├── MediaServerUserStatistics.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── movie │ │ │ │ │ ├── Movie.tsx │ │ │ │ │ ├── MovieRow.tsx │ │ │ │ │ ├── MovieStatistics.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── settings │ │ │ │ │ ├── Settings.ts │ │ │ │ │ └── index.tsx │ │ │ │ ├── show │ │ │ │ │ ├── ShowRow.tsx │ │ │ │ │ ├── ShowStatistics.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── user │ │ │ │ │ ├── User.tsx │ │ │ │ │ └── index.tsx │ │ │ │ └── wizard │ │ │ │ │ ├── Wizard.tsx │ │ │ │ │ └── index.tsx │ │ │ ├── services │ │ │ │ ├── aboutService.tsx │ │ │ │ ├── accountService.tsx │ │ │ │ ├── axiosInstance.tsx │ │ │ │ ├── filterService.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── jobService.tsx │ │ │ │ ├── logService.tsx │ │ │ │ ├── movieService.tsx │ │ │ │ ├── serverService.tsx │ │ │ │ ├── settingsService.tsx │ │ │ │ ├── showService.tsx │ │ │ │ └── systemService.tsx │ │ │ └── utils │ │ │ │ ├── SnackbarUtilsConfigurator.tsx │ │ │ │ ├── calculateFileSize.tsx │ │ │ │ ├── convertToIcon.tsx │ │ │ │ ├── customWindow.tsx │ │ │ │ ├── generateStreamChipLabel.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── jobIds.tsx │ │ ├── styles │ │ │ └── theme.tsx │ │ └── tests │ │ │ ├── hooks │ │ │ └── useMediaServerUrls.test.tsx │ │ │ └── utils │ │ │ └── calculateFileSize.test.tsx │ └── tsconfig.json └── EmbyStat.Web.csproj ├── EmbyStat.sln ├── EmbyStat.sln.DotSettings ├── GitVersion.yml ├── LICENSE ├── README.md ├── Templates └── unraid │ ├── EmbyStatBeta.xml │ ├── unraid-blue-256px.png │ ├── unraid-blue-48px.png │ ├── unraid-blue-512px.png │ ├── unraid-blue-white_inside-256px.png │ ├── unraid-blue-white_inside-48px.png │ ├── unraid-blue-white_inside-512px.png │ ├── unraid-white&blue-256px.png │ ├── unraid-white&blue-48px.png │ ├── unraid-white&blue-512px.png │ ├── unraid-white-256px.png │ ├── unraid-white-48px.png │ └── unraid-white-512px.png ├── Tests.Unit ├── Builders │ ├── ConfigBuilder.cs │ ├── DeviceBuilder.cs │ ├── EpisodeBuilder.cs │ ├── FilterBuilder.cs │ ├── LibraryBuilder.cs │ ├── MediaServerUserBuilder.cs │ ├── MovieBuilder.cs │ ├── QueryResultBuilder.cs │ ├── SeasonBuilder.cs │ ├── ShowBuilder.cs │ ├── SubtitleStreamBuilder.cs │ ├── VideoStreamBuilder.cs │ └── ViewModels │ │ └── ConfigViewModelBuilder.cs ├── Clients │ ├── BaseHttpClientTests.cs │ ├── EmbyHttpClientTests.cs │ └── JellyFinHttpClientTests.cs ├── Controllers │ ├── FilterControllerTests.cs │ ├── JobControllerTests.cs │ ├── MediaServerControllerTests.cs │ ├── MovieControllerTests.cs │ ├── PluginControllerTests.cs │ ├── SettingsControllerTests.cs │ └── ShowControllerTests.cs ├── Converters │ └── TopCardConverterTests.cs ├── Extensions │ ├── DoubleExtensionTests.cs │ ├── IntExtensionTests.cs │ ├── ItemQueryExtensionTests.cs │ ├── ListExtensionTests.cs │ ├── MediServerExtensionTests.cs │ ├── MediaExtensionTests.cs │ ├── MovieExtensionTests.cs │ ├── RoundNumberExtensionTests.cs │ ├── ShowExtensionTests.cs │ └── StringExtensionTests.cs ├── Factory │ ├── EmbyClientFactoryTests.cs │ └── JellyfinClientFactoryTests.cs ├── Helpers │ ├── FakeRoleManager.cs │ ├── FakeSignInManager.cs │ └── FakeUserManager.cs ├── Jobs │ └── JobInitializerTests.cs ├── Models │ ├── EmbyUdpBroadcastTests.cs │ ├── MediaServerSettingsTests.cs │ └── StartupOptionsTests.cs ├── Services │ ├── AboutServiceTests.cs │ ├── AccountServiceTests.cs │ ├── FilterServiceTests.cs │ ├── JobServiceTests.cs │ ├── LanguageServiceTests.cs │ ├── LogServiceTests.cs │ ├── MediaServerServiceTests.cs │ ├── MovieServiceTests.cs │ ├── SessionServiceTests.cs │ ├── SettingsServiceTests.cs │ ├── ShowServiceTests.cs │ └── SystemServiceTests.cs └── Tests.Unit.csproj ├── Updater ├── Models │ └── StartupOptions.cs ├── Program.cs ├── Updater.cs ├── Updater.csproj └── nlog.config ├── branding ├── NSIS │ ├── install.ico │ ├── installer-header.bmp │ ├── installer-header.png │ ├── installer-right.bmp │ ├── installer-right.png │ └── uninstall.ico └── logo-color.png ├── builds ├── .vscode │ └── settings.json ├── beta.pipeline.yml ├── debian-x64 │ └── build.pipeline.yml ├── dev.pipeline.yml ├── docker-containers │ ├── arm.pipeline.yml │ ├── arm64.pipeline.yml │ ├── files │ │ ├── arm.dockerfile │ │ ├── arm64.dockerfile │ │ ├── linux.dockerfile │ │ ├── manifest-beta.yaml │ │ ├── manifest-nightly.yaml │ │ ├── manifest-tool-windows-amd64.exe │ │ └── win.dockerfile │ ├── linux.pipeline.yml │ ├── publishing │ │ ├── beta.publish.yml │ │ ├── dev.publish.yml │ │ ├── finish.yml │ │ └── publish.yml │ └── win.pipeline.yml ├── fedora-x64 │ └── build.pipeline.yml ├── linux-arm-x64 │ └── build.pipeline.yml ├── linux-arm │ └── build.pipeline.yml ├── scripts │ ├── appsettings.ps1 │ └── rollbar.ps1 ├── templates │ ├── download.artifact.yml │ ├── npmbuild.yml │ ├── sonarcloud.end.yml │ ├── sonarcloud.start.yml │ ├── test.stage.yml │ ├── unit.tests.yml │ ├── update.version.yml │ └── version.variables.yml ├── ubuntu-x64 │ ├── Dockerfile │ ├── build.pipeline.yml │ ├── clean.sh │ ├── docker-build.sh │ ├── package.sh │ └── pkg-src │ │ ├── changelog │ │ ├── compat │ │ ├── conf │ │ ├── embystat │ │ ├── embystat-sudoers │ │ ├── embystat.service.conf │ │ └── logging.json │ │ ├── control │ │ ├── copyright │ │ ├── embystat.init │ │ ├── embystat.service │ │ ├── embystat.upstart │ │ ├── gbp.conf │ │ ├── install │ │ ├── po │ │ ├── POTFILES.in │ │ └── templates.pot │ │ ├── postinst │ │ ├── postrm │ │ ├── preinst │ │ ├── prerm │ │ ├── rules │ │ └── source │ │ ├── format │ │ └── options ├── win-x64 │ └── build.pipeline.yml └── windows-installer │ ├── build.pipeline.yml │ ├── dialogs │ ├── confirmation.nsddef │ ├── confirmation.nsdinc │ ├── service-config.nsddef │ ├── service-config.nsdinc │ ├── setuptype.nsddef │ └── setuptype.nsdinc │ ├── embystat.nsi │ ├── helpers │ ├── ShowError.nsh │ └── StrSlash.nsh │ └── installer-build.ps1 ├── commands.txt ├── crowdin.yml ├── nuget.config └── version.json /.bettercodehub.yml: -------------------------------------------------------------------------------- 1 | component_depth: 1 2 | 3 | languages: 4 | - csharp 5 | - javascript 6 | - typescript 7 | 8 | exclude: 9 | - /EmbyStat.Clients/EmbyClient/.* 10 | - /EmbyStat.Common/Helpers/.* 11 | - /EmbyStat.Common/Models/.* 12 | - /EmbyStat.Common/Constants.cs 13 | - /EmbyStat.Common/Converters/.* 14 | - /EmbyStat.Controllers/ViewModels/.* 15 | - /EmbyStat.Controllers/MapProfiles.cs 16 | - /EmbyStat.DI/DIExtentions.cs 17 | - /EmbyStat.Repositories/ApplicationDbContext.cs 18 | - /EmbyStat.Repositories/DatabaseInitializer.cs 19 | - /EmbyStat.Repositories/Migrations/.* 20 | - /EmbyStat.Web/ClientApp/.* 21 | - /EmbyStat.Web/Startup.cs 22 | - /Tests.Integration/.* 23 | - /Tests.Unit/.* -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | #Projects 2 | **/Tests.Integration 3 | **/Tests.Unit 4 | 5 | 6 | #Folders 7 | **/[Bb]in 8 | **/[Oo]bj 9 | **/node_modules 10 | **/dist 11 | **/wwwroot 12 | **/output 13 | **/.vs 14 | **/.github 15 | **/.git 16 | **/.sonarqube 17 | **/.gitattributes 18 | **/.gitignore 19 | 20 | #File extentions 21 | *_i.c 22 | *_p.c 23 | *.ilk 24 | *.meta 25 | *.obj 26 | *.pch 27 | *.pdb 28 | *.pgc 29 | *.pgd 30 | *.rsp 31 | *.sbr 32 | *.tlb 33 | *.tli 34 | *.tlh 35 | *.tmp 36 | *.log 37 | *.vspscc 38 | *.vssscc 39 | *.md 40 | *.yml 41 | *.trc 42 | *.sln 43 | *.DotSettings 44 | *.suo 45 | *.user 46 | *.sln.docstates 47 | LICENSE -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | ko_fi: embystat 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | # Feature request 7 | 8 | **Is your feature request related to a problem? Please describe. 9 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 10 | 11 | **Describe the solution you'd like 12 | A clear and concise description of what you want to happen. 13 | 14 | **Describe alternatives you've considered 15 | A clear and concise description of any alternative solutions or features you've considered. 16 | 17 | **Additional context 18 | Add any other context or screenshots about the feature request here. 19 | -------------------------------------------------------------------------------- /.github/dco.yml: -------------------------------------------------------------------------------- 1 | require: 2 | members: false -------------------------------------------------------------------------------- /.github/workflows/label.yml: -------------------------------------------------------------------------------- 1 | # This workflow will triage pull requests and apply a label based on the 2 | # paths that are modified in the pull request. 3 | # 4 | # To use this workflow, you will need to set up a .github/labeler.yml 5 | # file with configuration. For more information, see: 6 | # https://github.com/actions/labeler/blob/master/README.md 7 | 8 | name: Labeler 9 | on: [pull_request] 10 | 11 | jobs: 12 | label: 13 | 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/labeler@v2 18 | with: 19 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 20 | -------------------------------------------------------------------------------- /.github/workflows/new-translations.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - l10n_develop 7 | 8 | jobs: 9 | build: 10 | 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Pushbullet Notification 15 | uses: ShaunLWM/action-pushbullet@0.0.1 16 | with: 17 | PB_TOKEN: o.HM9iALoW4oZVLKfWpBHqs5DmE06M2ilV 18 | -------------------------------------------------------------------------------- /EmbyStat.Clients.Base/Http/IRefitHttpClientFactory.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Clients.Base.Http; 2 | 3 | public interface IRefitHttpClientFactory 4 | { 5 | T CreateClient(string baseAddressKey); 6 | } -------------------------------------------------------------------------------- /EmbyStat.Clients.Base/Http/RefitHttpClientFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.Http; 3 | using Refit; 4 | 5 | namespace EmbyStat.Clients.Base.Http; 6 | 7 | public class RefitHttpClientFactory : IRefitHttpClientFactory 8 | { 9 | private readonly IHttpClientFactory _clientFactory; 10 | 11 | public RefitHttpClientFactory(IHttpClientFactory clientFactory) 12 | { 13 | _clientFactory = clientFactory; 14 | } 15 | 16 | public T CreateClient(string baseAddressKey) 17 | { 18 | var client = _clientFactory.CreateClient("mediaServerClient"); 19 | client.BaseAddress = new Uri(baseAddressKey); 20 | 21 | return RestService.For(client); 22 | } 23 | } -------------------------------------------------------------------------------- /EmbyStat.Clients.Base/IClientFactory.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Clients.Base.Http; 2 | using EmbyStat.Clients.Base.WebSocket; 3 | using EmbyStat.Common.Enums; 4 | 5 | namespace EmbyStat.Clients.Base; 6 | 7 | public interface IClientFactory 8 | { 9 | IBaseHttpClient CreateHttpClient(); 10 | IWebSocketClient CreateWebSocketClient(); 11 | bool AppliesTo(ServerType type); 12 | } -------------------------------------------------------------------------------- /EmbyStat.Clients.Base/IClientStrategy.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Clients.Base.Http; 2 | using EmbyStat.Clients.Base.Metadata; 3 | using EmbyStat.Clients.Base.WebSocket; 4 | using EmbyStat.Common.Enums; 5 | 6 | namespace EmbyStat.Clients.Base; 7 | 8 | public interface IClientStrategy 9 | { 10 | IBaseHttpClient CreateHttpClient(ServerType type); 11 | IWebSocketClient CreateWebSocketClient(ServerType type); 12 | IMetadataClient CreateMetadataClient(MetadataServerType type); 13 | } -------------------------------------------------------------------------------- /EmbyStat.Clients.Base/IMetadataClientFactory.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Clients.Base.Metadata; 2 | using EmbyStat.Common.Enums; 3 | 4 | namespace EmbyStat.Clients.Base; 5 | 6 | public interface IMetadataClientFactory 7 | { 8 | IMetadataClient CreateClient(); 9 | bool AppliesTo(MetadataServerType type); 10 | } -------------------------------------------------------------------------------- /EmbyStat.Clients.Base/Metadata/IMetadataClient.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using EmbyStat.Common.Models.Show; 4 | 5 | namespace EmbyStat.Clients.Base.Metadata; 6 | 7 | public interface IMetadataClient 8 | { 9 | Task> GetEpisodesAsync(int? id); 10 | } -------------------------------------------------------------------------------- /EmbyStat.Clients.Base/WebSocket/IWebSocketClient.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Clients.Base.WebSocket; 2 | 3 | public interface IWebSocketClient 4 | { 5 | } -------------------------------------------------------------------------------- /EmbyStat.Clients.Emby/EmbyStat.Clients.Emby.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | 0.0.0.0 6 | 0.0.0.0 7 | 0.0.0.0 8 | 9 | {0145B376-DB18-42A2-B2AF-98B4A952002F} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /EmbyStat.Clients.Emby/Http/IEmbyBaseHttpClient.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Clients.Base.Http; 2 | 3 | namespace EmbyStat.Clients.Emby.Http; 4 | 5 | public interface IEmbyBaseHttpClient : IBaseHttpClient 6 | { 7 | 8 | } -------------------------------------------------------------------------------- /EmbyStat.Clients.Emby/WebSocket/IEmbyWebSocketClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.WebSockets; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using WebSocketState = WebSocket4Net.WebSocketState; 6 | 7 | namespace EmbyStat.Clients.Emby.WebSocket; 8 | 9 | public interface IEmbyWebSocketClient : IDisposable 10 | { 11 | event EventHandler Closed; 12 | event EventHandler Connected; 13 | Action OnReceiveBytes { get; set; } 14 | Action OnReceive { get; set; } 15 | WebSocketState State { get; } 16 | Task ConnectAsync(string url); 17 | Task CloseConnection(); 18 | Task SendAsync(byte[] bytes, WebSocketMessageType type, bool endOfMessage, CancellationToken cancellationToken); 19 | } -------------------------------------------------------------------------------- /EmbyStat.Clients.GitHub/EmbyStat.Clients.GitHub.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | 0.0.0.0 6 | 0.0.0.0 7 | 0.0.0.0 8 | 9 | {7243326A-D3F9-4C14-BAAD-86BF66D4F223} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /EmbyStat.Clients.GitHub/IGitHubApi.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using EmbyStat.Clients.GitHub.Models; 3 | using Refit; 4 | 5 | namespace EmbyStat.Clients.GitHub; 6 | 7 | public interface IGitHubApi 8 | { 9 | /// 10 | /// Fetches all releases from the public EmbyStat repo. 11 | /// 12 | /// Array of type 13 | [Get("/releases")] 14 | Task GetReleases(); 15 | } -------------------------------------------------------------------------------- /EmbyStat.Clients.GitHub/IGitHubClient.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using EmbyStat.Clients.GitHub.Models; 3 | 4 | namespace EmbyStat.Clients.GitHub; 5 | 6 | public interface IGitHubClient 7 | { 8 | Task GetGithubVersions(); 9 | } -------------------------------------------------------------------------------- /EmbyStat.Clients.GitHub/Models/PackageInfo.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Enums; 2 | using Newtonsoft.Json; 3 | 4 | namespace EmbyStat.Clients.GitHub.Models; 5 | 6 | public class PackageInfo 7 | { 8 | [JsonProperty("name")] 9 | public string Name { get; set; } 10 | [JsonProperty("versionStr")] 11 | public string VersionStr { get; set; } 12 | [JsonProperty("classification")] 13 | public UpdateTrain Classification { get; set; } 14 | [JsonProperty("sourceUrl")] 15 | public string SourceUrl { get; set; } 16 | [JsonProperty("infoUrl")] 17 | public string InfoUrl { get; set; } 18 | } -------------------------------------------------------------------------------- /EmbyStat.Clients.GitHub/Models/UpdateResult.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Clients.GitHub.Models; 2 | 3 | public class UpdateResult 4 | { 5 | public UpdateResult() 6 | { 7 | IsUpdateAvailable = false; 8 | Package = new PackageInfo(); 9 | } 10 | public bool IsUpdateAvailable { get; set; } 11 | public string AvailableVersion { get; set; } 12 | public PackageInfo Package { get; set; } 13 | } -------------------------------------------------------------------------------- /EmbyStat.Clients.Jellyfin/EmbyStat.Clients.Jellyfin.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | {BE8AFEF2-E5F4-40A5-8413-C2C2190C021E} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /EmbyStat.Clients.Jellyfin/Http/IJellyfinBaseHttpClient.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Clients.Base.Http; 2 | 3 | namespace EmbyStat.Clients.Jellyfin.Http; 4 | 5 | public interface IJellyfinBaseHttpClient : IBaseHttpClient 6 | { 7 | } -------------------------------------------------------------------------------- /EmbyStat.Clients.Jellyfin/WebSocket/IJellyfinWebSocketClient.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Clients.Jellyfin.WebSocket; 2 | 3 | public interface IJellyfinWebSocketClient 4 | { 5 | } -------------------------------------------------------------------------------- /EmbyStat.Clients.Tmdb/EmbyStat.Clients.Tmdb.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | {BE8AFEF2-E5F4-40A5-8413-C2C2190A061E} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /EmbyStat.Clients.Tmdb/ITmdbClient.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Clients.Base.Metadata; 2 | 3 | namespace EmbyStat.Clients.Tmdb; 4 | 5 | public interface ITmdbClient : IMetadataClient 6 | { 7 | 8 | } -------------------------------------------------------------------------------- /EmbyStat.Clients.Tmdb/TmdbClientFactory.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Clients.Base; 2 | using EmbyStat.Clients.Base.Metadata; 3 | using EmbyStat.Common.Enums; 4 | 5 | namespace EmbyStat.Clients.Tmdb; 6 | 7 | public class TmdbClientFactory : IMetadataClientFactory 8 | { 9 | private readonly ITmdbClient _client; 10 | 11 | public TmdbClientFactory(ITmdbClient client) 12 | { 13 | _client = client; 14 | } 15 | 16 | public IMetadataClient CreateClient() 17 | { 18 | return _client; 19 | } 20 | 21 | public bool AppliesTo(MetadataServerType type) 22 | { 23 | return type == MetadataServerType.Tmdb; 24 | } 25 | } -------------------------------------------------------------------------------- /EmbyStat.Clients.TvMaze/EmbyStat.Clients.TvMaze.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /EmbyStat.Clients.TvMaze/ITvMazeShowClient.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Clients.Base.Metadata; 2 | 3 | namespace EmbyStat.Clients.TvMaze; 4 | 5 | public interface ITvMazeShowClient : IMetadataClient 6 | { 7 | 8 | } -------------------------------------------------------------------------------- /EmbyStat.Clients.TvMaze/TvMazeClientFactory.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Clients.Base; 2 | using EmbyStat.Clients.Base.Metadata; 3 | using EmbyStat.Common.Enums; 4 | 5 | namespace EmbyStat.Clients.TvMaze; 6 | 7 | public class TvMazeClientFactory : IMetadataClientFactory 8 | { 9 | private readonly ITvMazeShowClient _showClient; 10 | 11 | public TvMazeClientFactory(ITvMazeShowClient showClient) 12 | { 13 | _showClient = showClient; 14 | } 15 | 16 | public IMetadataClient CreateClient() 17 | { 18 | return _showClient; 19 | } 20 | 21 | public bool AppliesTo(MetadataServerType type) 22 | { 23 | return type == MetadataServerType.TvMaze; 24 | } 25 | } -------------------------------------------------------------------------------- /EmbyStat.Common/ChartGrouping.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace EmbyStat.Common; 5 | 6 | public class ChartGrouping : List, IGrouping 7 | { 8 | public TKey Key 9 | { 10 | get; 11 | set; 12 | } 13 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Enums/CardType.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Enums; 2 | 3 | public enum CardType 4 | { 5 | Text = 0, 6 | Size = 1, 7 | Time = 2, 8 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Enums/ImageType.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Enums; 2 | 3 | public enum ImageType 4 | { 5 | Primary, 6 | Art, 7 | Backdrop, 8 | Banner, 9 | Logo, 10 | Thumb, 11 | Disc, 12 | Box, 13 | Screenshot, 14 | Menu, 15 | Chapter, 16 | BoxRear, 17 | Thumbnail, 18 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Enums/LibraryType.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Enums; 2 | 3 | public enum LibraryType 4 | { 5 | Other = 0, 6 | Movies = 1, 7 | TvShow = 2, 8 | Music = 3, 9 | MusicVideos = 4, 10 | Trailers = 5, 11 | HomeVideos = 6, 12 | Books = 8, 13 | Photos = 9, 14 | Games = 10, 15 | LiveTv = 11, 16 | Playlists = 12, 17 | Folders = 13, 18 | BoxSets = 14 19 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Enums/LocationType.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Enums; 2 | 3 | public enum LocationType 4 | { 5 | Disk = 0, 6 | Virtual = 1 7 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Enums/MediaProtocol.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Enums; 2 | 3 | public enum MediaProtocol 4 | { 5 | File, 6 | Http, 7 | Rtmp, 8 | Rtsp, 9 | Udp, 10 | Rtp, 11 | Ftp, 12 | Mms, 13 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Enums/MediaStreamType.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Enums; 2 | 3 | public enum MediaStreamType 4 | { 5 | Unknown = 0, 6 | Audio = 1, 7 | Video = 2, 8 | Subtitle = 3, 9 | EmbeddedImage = 4, 10 | Attachment = 5, 11 | Data = 6 12 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Enums/MediaType.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Enums; 2 | 3 | public enum MediaType 4 | { 5 | Unknown = 0, 6 | Movie = 1, 7 | Episode = 2, 8 | TvChannel = 3, 9 | Trailer = 4 10 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Enums/MetadataServerType.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Enums; 2 | 3 | public enum MetadataServerType 4 | { 5 | Tmdb = 0, 6 | TvMaze = 1 7 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Enums/PersonType.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Enums; 2 | 3 | public enum PersonType 4 | { 5 | Actor = 0, 6 | Director = 1, 7 | Writer = 2, 8 | Producer = 3, 9 | GuestStar = 4, 10 | Composer = 5, 11 | Conductor = 6, 12 | Lyricist = 7, 13 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Enums/PlayMethod.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Enums; 2 | 3 | public enum PlayMethod 4 | { 5 | Transcode = 0, 6 | DirectStream = 1, 7 | DirectPlay = 2, 8 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Enums/RepeatMode.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Enums; 2 | 3 | public enum RepeatMode 4 | { 5 | RepeatNone = 0, 6 | RepeatAll = 1, 7 | RepeatOne = 2 8 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Enums/ServerType.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Enums; 2 | 3 | public enum ServerType 4 | { 5 | Emby = 0, 6 | Jellyfin = 1 7 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Enums/StatisticType.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Enums; 2 | 3 | public enum StatisticType 4 | { 5 | Movie = 0, 6 | Show = 1, 7 | User = 2 8 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Enums/UpdateLevel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Enums; 2 | 3 | public enum UpdateLevel 4 | { 5 | Release, 6 | Beta, 7 | Dev 8 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Enums/UpdateTrain.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Enums; 2 | 3 | public enum UpdateTrain 4 | { 5 | Dev = 0, 6 | Beta = 1, 7 | Release = 2 8 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Enums/Video3DFormat.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Enums; 2 | 3 | public enum Video3DFormat 4 | { 5 | None = 0, 6 | HalfSideBySide = 1, 7 | FullSideBySide = 2, 8 | FullTopAndBottom = 3, 9 | HalfTopAndBottom = 4, 10 | MVC = 5, 11 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Exceptions/ApiError.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Exceptions; 2 | 3 | public class ApiError 4 | { 5 | public string Message { get; } 6 | public bool IsError { get; } 7 | public string Stack { get; } 8 | 9 | public ApiError(string message, string stack, bool isError) 10 | { 11 | Message = message; 12 | Stack = stack; 13 | IsError = isError; 14 | } 15 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Exceptions/BusinessException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmbyStat.Common.Exceptions; 4 | 5 | public class BusinessException : Exception 6 | { 7 | public int StatusCode { get; set; } 8 | 9 | public BusinessException(string message, int statusCode = 500, Exception e = null) : base(message, e) 10 | { 11 | StatusCode = statusCode; 12 | } 13 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Exceptions/EmbyStatStartupException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmbyStat.Common.Exceptions; 4 | 5 | public class EmbyStatStartupException : Exception 6 | { 7 | public EmbyStatStartupException(Exception innerException) 8 | : base("EmbyStat failed to start: " + innerException.Message) 9 | { 10 | 11 | } 12 | 13 | public EmbyStatStartupException(Exception innerException, string message) 14 | : base("EmbyStat failed to start: " + message, innerException) 15 | { 16 | } 17 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Exceptions/NotFoundException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmbyStat.Common.Exceptions; 4 | 5 | public class NotFoundException : Exception 6 | { 7 | public NotFoundException(string message) : base(message) 8 | { 9 | 10 | } 11 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Exceptions/WizardNotFinishedException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmbyStat.Common.Exceptions; 4 | 5 | public class WizardNotFinishedException : Exception 6 | { 7 | public WizardNotFinishedException(string message):base(message) 8 | { 9 | 10 | } 11 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Extensions/DoubleExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | 3 | namespace EmbyStat.Common.Extensions; 4 | 5 | public static class DoubleExtensions 6 | { 7 | public static string FormatToDotDecimalString(this double value) 8 | { 9 | return value 10 | .ToString(CultureInfo.CurrentCulture) 11 | .Replace(",", "."); 12 | } 13 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Extensions/LibrarySyncTypeExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using EmbyStat.Common.Enums; 6 | using EmbyStat.Common.Models.Entities; 7 | 8 | namespace EmbyStat.Common.Extensions; 9 | 10 | public static class LibrarySyncTypeExtensions 11 | { 12 | public static DateTime? GetLastSyncedDateForLibrary(this IEnumerable items, string libraryId, LibraryType type) 13 | { 14 | return items.FirstOrDefault(x => x.LibraryId == libraryId && x.SyncType == type)?.LastSynced; 15 | } 16 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Extensions/VirtualEpisodeExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EmbyStat.Common.Enums; 3 | using EmbyStat.Common.Models.Entities.Shows; 4 | using EmbyStat.Common.Models.Show; 5 | 6 | namespace EmbyStat.Common.Extensions; 7 | 8 | public static class VirtualEpisodeExtensions 9 | { 10 | public static Episode ConvertToVirtualEpisode(this VirtualEpisode episode, Season season) 11 | { 12 | return new Episode 13 | { 14 | Id = Guid.NewGuid().ToString(), 15 | Name = episode.Name, 16 | LocationType = LocationType.Virtual, 17 | IndexNumber = episode.EpisodeNumber, 18 | SeasonId = season.Id, 19 | PremiereDate = episode.FirstAired ?? new DateTime() 20 | }; 21 | } 22 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Helpers/ListContainer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace EmbyStat.Common.Helpers; 4 | 5 | public class ListContainer 6 | { 7 | public int TotalCount { get; set; } 8 | public IEnumerable Data { get; set; } 9 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Account/AccessToken.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Models.Account; 2 | 3 | public class AccessToken 4 | { 5 | public string Token { get; } 6 | public int ExpiresIn { get; } 7 | 8 | public AccessToken(string token, int expiresIn) 9 | { 10 | Token = token; 11 | ExpiresIn = expiresIn; 12 | } 13 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Account/AuthenticateRequest.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Models.Account; 2 | 3 | public class AuthenticateRequest 4 | { 5 | public string Password { get; set; } 6 | public string Username { get; set; } 7 | public bool RememberMe { get; set; } 8 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Account/AuthenticateResponse.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Models.Account; 2 | 3 | public class AuthenticateResponse 4 | { 5 | public string AccessToken { get; set; } 6 | public string RefreshToken { get; set; } 7 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Account/ChangePasswordRequest.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Models.Account; 2 | 3 | public class ChangePasswordRequest 4 | { 5 | public string UserName { get; set; } 6 | public string OldPassword { get; set; } 7 | public string NewPassword { get; set; } 8 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Account/ChangeUserNameRequest.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Models.Account; 2 | 3 | public class ChangeUserNameRequest 4 | { 5 | public string OldUserName { get; set; } 6 | public string UserName { get; set; } 7 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Account/RefreshTokenRequest.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Models.Account; 2 | 3 | public class RefreshTokenRequest 4 | { 5 | public string AccessToken { get; set; } 6 | public string RefreshToken { get; set; } 7 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Cards/Card.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Enums; 2 | 3 | namespace EmbyStat.Common.Models.Cards; 4 | 5 | public class Card 6 | { 7 | public string Title { get; set; } 8 | public string Value { get; set; } 9 | public CardType Type { get; set; } 10 | public string Icon { get; set; } 11 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Cards/TopCard.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Models.Cards; 2 | 3 | public class TopCard 4 | { 5 | public string Title { get; set; } 6 | public string Unit { get; set; } 7 | public bool UnitNeedsTranslation { get; set; } 8 | public ValueType ValueType { get; set; } 9 | public TopCardItem[] Values { get; set; } 10 | } 11 | 12 | public class TopCardItem 13 | { 14 | public string MediaId { get; set; } 15 | public string Image { get; set; } 16 | public string Label { get; set; } 17 | public string Value { get; set; } 18 | } 19 | 20 | public enum ValueType 21 | { 22 | None = 0, 23 | Ticks = 1, 24 | Date = 2, 25 | SizeInMb = 3 26 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Charts/Chart.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Models.Charts; 2 | 3 | public class Chart 4 | { 5 | public string Title { get; set; } 6 | public SimpleChartData[] DataSets { get; set; } 7 | public int SeriesCount { get; set; } 8 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Charts/SimpleChartData.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Models.Charts; 2 | 3 | public class SimpleChartData 4 | { 5 | public string Label { get; set; } 6 | public double Value { get; set; } 7 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/DataGrid/Page.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace EmbyStat.Common.Models.DataGrid; 4 | 5 | public class Page 6 | { 7 | public IEnumerable Data { get; set; } 8 | public int TotalCount { get; set; } 9 | 10 | public Page(IEnumerable data) 11 | { 12 | Data = data; 13 | } 14 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Device.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmbyStat.Common.Models.Entities; 4 | 5 | public class Device 6 | { 7 | public string Id { get; set; } 8 | public string Name { get; set; } 9 | public string LastUserName { get; set; } 10 | public string AppName { get; set; } 11 | public string AppVersion { get; set; } 12 | public string LastUserId { get; set; } 13 | public DateTime? DateLastActivity { get; set; } 14 | public string IconUrl { get; set; } 15 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Events/PlayState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using EmbyStat.Common.Enums; 4 | 5 | namespace EmbyStat.Common.Models.Entities.Events; 6 | 7 | public class PlayState 8 | { 9 | public long? PositionTicks { get; set; } 10 | public int? VolumeLevel { get; set; } 11 | public string MediaSourceId { get; set; } 12 | public PlayMethod? PlayMethod { get; set; } 13 | public RepeatMode RepeatMode { get; set; } 14 | public bool IsTranscoding { get; set; } 15 | public bool IsPaused { get; set; } 16 | public List TranscodeReasons { get; set; } 17 | public string AudioCodec { get; set; } 18 | public string VideoCodec { get; set; } 19 | public DateTime TimeLogged { get; set; } 20 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Events/Session.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace EmbyStat.Common.Models.Entities.Events; 4 | 5 | public class Session 6 | { 7 | public string Id { get; set; } 8 | public string ServerId { get; set; } 9 | public string ApplicationVersion { get; set; } 10 | public string Client { get; set; } 11 | public string DeviceId { get; set; } 12 | public string AppIconUrl { get; set; } 13 | public string UserId { get; set; } 14 | public List Plays { get; set; } 15 | public Session() 16 | { 17 | Plays = new List(); 18 | } 19 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Genre.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using EmbyStat.Common.Models.Entities.Movies; 3 | 4 | namespace EmbyStat.Common.Models.Entities; 5 | 6 | public class Genre 7 | { 8 | public string Id { get; set; } 9 | public string Name { get; set; } 10 | public ICollection Movies { get; set; } 11 | public ICollection Shows { get; set; } 12 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Helpers/Extra.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Models.Entities.Helpers; 2 | 3 | public abstract class Extra : Media 4 | { 5 | public decimal? CommunityRating { get; set; } 6 | public string IMDB { get; set; } 7 | public int? TMDB { get; set; } 8 | public int? TVDB { get; set; } 9 | public long? RunTimeTicks { get; set; } 10 | public string OfficialRating { get; set; } 11 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Helpers/ILinkedMedia.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace EmbyStat.Common.Models.Entities.Helpers; 4 | 5 | public interface ILinkedMedia 6 | { 7 | ICollection People { get; set; } 8 | ICollection Genres { get; set; } 9 | Library Library { get; set; } 10 | public string LibraryId { get; set; } 11 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Helpers/LabelValuePair.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace EmbyStat.Common.Models.Entities.Helpers; 4 | 5 | public class LabelValuePair : IEqualityComparer 6 | { 7 | public string Label { get; set; } 8 | public string Value { get; set; } 9 | 10 | public bool Equals(LabelValuePair x, LabelValuePair y) 11 | { 12 | if (ReferenceEquals(x, y)) return true; 13 | if (ReferenceEquals(x, null)) return false; 14 | if (ReferenceEquals(y, null)) return false; 15 | if (x.GetType() != y.GetType()) return false; 16 | return x.Label == y.Label; 17 | } 18 | 19 | public int GetHashCode(LabelValuePair obj) 20 | { 21 | return (obj.Label != null ? obj.Label.GetHashCode() : 0); 22 | } 23 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Helpers/Media.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmbyStat.Common.Models.Entities.Helpers; 4 | 5 | public abstract class Media 6 | { 7 | public string Id { get; set; } 8 | public DateTime? DateCreated { get; set; } 9 | public string Banner { get; set; } 10 | public string Logo { get; set; } 11 | public string Primary { get; set; } 12 | public string Thumb { get; set; } 13 | public string Name { get; set; } 14 | public string Path { get; set; } 15 | public DateTime? PremiereDate { get; set; } 16 | public int? ProductionYear { get; set; } 17 | public string SortName { get; set; } 18 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Helpers/RefreshToken.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmbyStat.Common.Models.Entities.Helpers; 4 | 5 | public class RefreshToken 6 | { 7 | public Guid Id { get; set; } 8 | public string Token { get; } 9 | public DateTime Expires { get; } 10 | public string UserId { get; } 11 | public bool Active => DateTime.UtcNow <= Expires; 12 | public string RemoteIpAddress { get; } 13 | 14 | public RefreshToken() 15 | { 16 | 17 | } 18 | 19 | public RefreshToken(string token, DateTime expires, string userId, string remoteIpAddress) 20 | { 21 | Token = token; 22 | Expires = expires; 23 | UserId = userId; 24 | RemoteIpAddress = remoteIpAddress; 25 | } 26 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Helpers/Video.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using EmbyStat.Common.Enums; 3 | using EmbyStat.Common.Models.Entities.Streams; 4 | 5 | namespace EmbyStat.Common.Models.Entities.Helpers; 6 | 7 | public abstract class Video : Extra 8 | { 9 | public string Container { get; set; } 10 | public Video3DFormat Video3DFormat { get; set; } 11 | public ICollection MediaSources { get; set; } 12 | public ICollection VideoStreams { get; set; } 13 | public ICollection AudioStreams { get; set; } 14 | public ICollection SubtitleStreams { get; set; } 15 | public ICollection Views { get; set; } 16 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Language.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Models.Entities; 2 | 3 | public class Language 4 | { 5 | public string Id { get; set; } 6 | public string Name { get; set; } 7 | public string Code { get; set; } 8 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Library.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using EmbyStat.Common.Enums; 4 | using EmbyStat.Common.Models.Entities.Movies; 5 | 6 | namespace EmbyStat.Common.Models.Entities; 7 | 8 | public class Library 9 | { 10 | public string Id { get; set; } 11 | public string Name { get; set; } 12 | public string Primary { get; set; } 13 | public LibraryType Type { get; set; } 14 | public ICollection Movies { get; set; } 15 | public ICollection Shows { get; set; } 16 | public ICollection SyncTypes { get; set; } 17 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/LibrarySyncType.cs: -------------------------------------------------------------------------------- 1 |  using System; 2 | using EmbyStat.Common.Enums; 3 | 4 | namespace EmbyStat.Common.Models.Entities; 5 | 6 | public class LibrarySyncType 7 | { 8 | public string Id { get; set; } 9 | public string LibraryId { get; set; } 10 | public Library Library { get; set; } 11 | public LibraryType SyncType { get; set; } 12 | public DateTime? LastSynced { get; set; } 13 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/MediaServerStatus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmbyStat.Common.Models.Entities; 4 | 5 | public class MediaServerStatus 6 | { 7 | public Guid Id { get; set; } 8 | public int MissedPings { get; set; } 9 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/MediaServerUserView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EmbyStat.Common.Enums; 3 | using EmbyStat.Common.Models.Entities.Users; 4 | 5 | namespace EmbyStat.Common.Models.Entities; 6 | 7 | public class MediaServerUserView 8 | { 9 | public string UserId { get; set; } 10 | public MediaServerUser User { get; set; } 11 | public MediaType MediaType { get; set; } 12 | public string MediaId { get; set; } 13 | public int PlayCount { get; set; } 14 | public DateTime LastPlayedDate { get; set; } 15 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Person.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using EmbyStat.Common.Models.Entities.Helpers; 3 | 4 | namespace EmbyStat.Common.Models.Entities; 5 | 6 | public class Person 7 | { 8 | public string Id { get; set; } 9 | public string Name { get; set; } 10 | public string Primary { get; set; } 11 | public ICollection MediaPeople { get; set; } 12 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/PluginInfo.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Models.Entities; 2 | 3 | public class PluginInfo 4 | { 5 | public string Id { get; set; } 6 | public string Name { get; set; } 7 | public string Version { get; set; } 8 | public string Description { get; set; } 9 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Shows/Episode.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Enums; 2 | using EmbyStat.Common.Models.Entities.Helpers; 3 | 4 | namespace EmbyStat.Common.Models.Entities.Shows; 5 | 6 | public class Episode : Video 7 | { 8 | public float? DvdEpisodeNumber { get; set; } 9 | public int? DvdSeasonNumber { get; set; } 10 | public int? IndexNumber { get; set; } 11 | public int? IndexNumberEnd { get; set; } 12 | public LocationType LocationType { get; set; } 13 | public Season Season { get; set; } 14 | public string SeasonId { get; set; } 15 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Shows/Season.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using EmbyStat.Common.Enums; 3 | using EmbyStat.Common.Models.Entities.Helpers; 4 | 5 | namespace EmbyStat.Common.Models.Entities.Shows; 6 | 7 | public class Season : Media 8 | { 9 | public int? IndexNumber { get; set; } 10 | public int? IndexNumberEnd { get; set; } 11 | public LocationType LocationType { get; set; } 12 | public ICollection Episodes { get; set; } 13 | public Show Show { get; set; } 14 | public string ShowId { get; set; } 15 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Shows/Show.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using EmbyStat.Common.Models.Entities.Helpers; 3 | 4 | namespace EmbyStat.Common.Models.Entities.Shows; 5 | 6 | public class Show : Extra, ILinkedMedia 7 | { 8 | public long? CumulativeRunTimeTicks { get; set; } 9 | public string Status { get; set; } 10 | public bool ExternalSynced { get; set; } 11 | public double SizeInMb { get; set; } 12 | public ICollection Seasons { get; set; } 13 | 14 | #region Inherited props 15 | 16 | public ICollection People { get; set; } 17 | public ICollection Genres { get; set; } 18 | public Library Library { get; set; } 19 | public string LibraryId { get; set; } 20 | 21 | #endregion 22 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Statistic.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EmbyStat.Common.Enums; 3 | 4 | namespace EmbyStat.Common.Models.Entities; 5 | 6 | public class Statistic 7 | { 8 | public Guid Id { get; set; } 9 | public DateTime CalculationDateTime { get; set; } 10 | public StatisticType Type { get; set; } 11 | public string JsonResult { get; set; } 12 | public bool IsValid { get; set; } 13 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Streams/AudioStream.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Entities.Movies; 2 | using EmbyStat.Common.Models.Entities.Shows; 3 | 4 | namespace EmbyStat.Common.Models.Entities.Streams; 5 | 6 | public class AudioStream 7 | { 8 | public string Id { get; set; } 9 | public int? BitRate { get; set; } 10 | public string ChannelLayout { get; set; } 11 | public int? Channels { get; set; } 12 | public string Codec { get; set; } 13 | public string Language { get; set; } 14 | public int? SampleRate { get; set; } 15 | public bool IsDefault { get; set; } 16 | public Movie Movie { get; set; } 17 | public string MovieId { get; set; } 18 | public Episode Episode { get; set; } 19 | public string EpisodeId { get; set; } 20 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Streams/MediaSource.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Entities.Movies; 2 | using EmbyStat.Common.Models.Entities.Shows; 3 | 4 | namespace EmbyStat.Common.Models.Entities.Streams; 5 | 6 | public class MediaSource 7 | { 8 | public string Id { get; set; } 9 | public int? BitRate { get; set; } 10 | public string Container { get; set; } 11 | public string Path { get; set; } 12 | public string Protocol { get; set; } 13 | public long? RunTimeTicks { get; set; } 14 | public double SizeInMb { get; set; } 15 | public Movie Movie { get; set; } 16 | public string MovieId { get; set; } 17 | public Episode Episode { get; set; } 18 | public string EpisodeId { get; set; } 19 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Entities/Streams/SubtitleStream.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Entities.Movies; 2 | using EmbyStat.Common.Models.Entities.Shows; 3 | 4 | namespace EmbyStat.Common.Models.Entities.Streams; 5 | 6 | public class SubtitleStream 7 | { 8 | public string Id { get; set; } 9 | public string Codec { get; set; } 10 | public string DisplayTitle { get; set; } 11 | public bool IsDefault { get; set; } 12 | public string Language { get; set; } 13 | public Movie Movie { get; set; } 14 | public string MovieId { get; set; } 15 | public Episode Episode { get; set; } 16 | public string EpisodeId { get; set; } 17 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/GenericEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmbyStat.Common.Models; 4 | 5 | public class GenericEventArgs : EventArgs 6 | { 7 | public T Argument { get; set; } 8 | 9 | public GenericEventArgs(T arg) 10 | { 11 | Argument = arg; 12 | } 13 | 14 | public GenericEventArgs() 15 | { 16 | } 17 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/MediaServer/MediaServerUserRow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmbyStat.Common.Models.MediaServer; 4 | 5 | public class MediaServerUserRow 6 | { 7 | public string Id { get; set; } 8 | public string Name { get; set; } 9 | public DateTime? LastActivityDate { get; set; } 10 | public bool IsAdministrator { get; set; } 11 | public bool IsHidden { get; set; } 12 | public bool IsDisabled { get; set; } 13 | public int MovieViewCount { get; set; } 14 | public int EpisodeViewCount { get; set; } 15 | public int TotalViewCount { get; set; } 16 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/MediaServer/UserMediaView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmbyStat.Common.Models.MediaServer; 4 | 5 | public class UserMediaView 6 | { 7 | public string Id { get; set; } 8 | public string Primary { get; set; } 9 | public string Name { get; set; } 10 | public decimal? WatchedPercentage { get; set; } 11 | public double WatchedTime { get; set; } 12 | public DateTimeOffset StartedWatching { get; set; } 13 | public DateTimeOffset EndedWatching { get; set; } 14 | public string DeviceId { get; set; } 15 | public string DeviceLogo { get; set; } 16 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Net/BaseItemPerson.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Enums; 2 | 3 | namespace EmbyStat.Common.Models.Net; 4 | 5 | public class BaseItemPerson 6 | { 7 | public string Name { get; set; } 8 | public string Id { get; set; } 9 | public PersonType Type { get; set; } 10 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Net/BaseMediaSourceInfo.cs: -------------------------------------------------------------------------------- 1 |  2 | using EmbyStat.Common.Enums; 3 | 4 | namespace EmbyStat.Common.Models.Net; 5 | 6 | public class BaseMediaSourceInfo 7 | { 8 | public string Id { get; set; } 9 | public string Path { get; set; } 10 | public int? Bitrate { get; set; } 11 | public string Container { get; set; } 12 | public MediaProtocol Protocol { get; set; } 13 | public long? RunTimeTicks { get; set; } 14 | public long? Size { get; set; } 15 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Net/UserData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmbyStat.Common.Models.Net; 4 | 5 | public class UserData 6 | { 7 | public long PlaybackPositionTicks { get; set; } 8 | public int PlayCount { get; set; } 9 | 10 | public bool IsFavorite { get; set; } 11 | public DateTime LastPlayedDate { get; set; } 12 | 13 | public bool Played { get; set; } 14 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Query/Filter.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Models.Query; 2 | 3 | public class Filter 4 | { 5 | public string Value { get; init; } 6 | public string Operation { get; init; } 7 | public string Field { get; init; } 8 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Show/VirtualEpisode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmbyStat.Common.Models.Show; 4 | 5 | public class VirtualEpisode 6 | { 7 | public string Id { get; set; } 8 | public string Name { get; set; } 9 | public int SeasonNumber { get; set; } 10 | public int EpisodeNumber { get; set; } 11 | public DateTime? FirstAired { get; set; } 12 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Tasks/Enum/JobState.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Models.Tasks.Enum; 2 | 3 | public enum JobState 4 | { 5 | Idle = 0, 6 | Running = 1, 7 | Failed = 2, 8 | Completed = 3 9 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Tasks/Enum/ProgressLogType.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Models.Tasks.Enum; 2 | 3 | public enum ProgressLogType 4 | { 5 | Information = 0, 6 | Warning = 1, 7 | Error = 2 8 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Tasks/JobLog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EmbyStat.Common.Models.Tasks.Enum; 3 | 4 | namespace EmbyStat.Common.Models.Tasks; 5 | 6 | public class JobLog 7 | { 8 | public string JobName { get; set; } 9 | public string Value { get; set; } 10 | public DateTime DateTimeUtc { get; set; } 11 | public ProgressLogType Type { get; set; } 12 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/Tasks/JobProgress.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EmbyStat.Common.Models.Tasks.Enum; 3 | 4 | namespace EmbyStat.Common.Models.Tasks; 5 | 6 | public class JobProgress 7 | { 8 | public Guid Id { get; set; } 9 | public JobState State { get; set; } 10 | public double? CurrentProgressPercentage { get; set; } 11 | public DateTime StartTimeUtc { get; set; } 12 | public DateTime? EndTimeUtc { get; set; } 13 | } -------------------------------------------------------------------------------- /EmbyStat.Common/Models/WebSocketMessage.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Common.Models; 2 | 3 | public class WebSocketMessage 4 | { 5 | public string MessageType { get; set; } 6 | public T Data { get; set; } 7 | } -------------------------------------------------------------------------------- /EmbyStat.Configuration/EmbyStat.Configuration.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | {7243326B-D3F9-4C14-BAAD-86BF66D4F223} 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /EmbyStat.Configuration/Interfaces/IConfigurationService.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Configuration.Interfaces; 2 | 3 | public interface IConfigurationService 4 | { 5 | Config Get(); 6 | Task UpdateSystemConfiguration(SystemConfig config); 7 | Task UpdateUserConfiguration(UserConfig config); 8 | Task SetUpdateInProgressSettingAsync(bool state); 9 | } -------------------------------------------------------------------------------- /EmbyStat.Configuration/InvalidConfigFileException.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Configuration; 2 | 3 | public class InvalidConfigFileException : Exception 4 | { 5 | public InvalidConfigFileException(string message) 6 | : base(message) 7 | { 8 | } 9 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/About/AboutController.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using EmbyStat.Core.About.Interfaces; 3 | using Microsoft.AspNetCore.Mvc; 4 | 5 | namespace EmbyStat.Controllers.About; 6 | 7 | [Produces("application/json")] 8 | [Route("api/[controller]")] 9 | public class AboutController : Controller 10 | { 11 | private readonly IAboutService _aboutService; 12 | private readonly IMapper _mapper; 13 | 14 | public AboutController(IAboutService aboutService, IMapper mapper) 15 | { 16 | _aboutService = aboutService; 17 | _mapper = mapper; 18 | } 19 | 20 | [HttpGet] 21 | public IActionResult Get() 22 | { 23 | var about = _aboutService.GetAbout(); 24 | return Ok(_mapper.Map(about)); 25 | } 26 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/About/AboutViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.About; 2 | 3 | public class AboutViewModel 4 | { 5 | public string OperatingSystem { get; set; } 6 | public string OperatingSystemVersion { get; set; } 7 | public string Architecture { get; set; } 8 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/Filters/FilterValuesViewModel.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Controllers.HelperClasses; 2 | 3 | namespace EmbyStat.Controllers.Filters; 4 | 5 | public class FilterValuesViewModel 6 | { 7 | public string Id { get; set; } 8 | public string Field { get; set; } 9 | public LabelValuePairViewModel[] Values { get; set; } 10 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/HelperClasses/ActiveFilterViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.HelperClasses; 2 | 3 | public class ActiveFilterViewModel 4 | { 5 | public string Value { get; set; } 6 | public string Operation { get; set; } 7 | public string Field { get; set; } 8 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/HelperClasses/CardViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.HelperClasses; 2 | 3 | public class CardViewModel 4 | { 5 | public string Title { get; set; } 6 | public string Value { get; set; } 7 | public string Type { get; set; } 8 | public string Icon { get; set; } 9 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/HelperClasses/ChartViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.HelperClasses; 2 | 3 | public class ChartViewModel 4 | { 5 | public string Title { get; set; } 6 | public string DataSets { get; set; } 7 | public int SeriesCount { get; set; } 8 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/HelperClasses/LabelValuePairViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.HelperClasses; 2 | 3 | public class LabelValuePairViewModel 4 | { 5 | public string Label { get; set; } 6 | public string Value { get; set; } 7 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/HelperClasses/LibraryViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.HelperClasses; 2 | 3 | public class LibraryViewModel 4 | { 5 | public string Id { get; set; } 6 | public string Name { get; set; } 7 | public string Primary { get; set; } 8 | public int Type { get; set; } 9 | public bool Sync { get; set; } 10 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/HelperClasses/PageViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace EmbyStat.Controllers.HelperClasses; 4 | 5 | public class PageViewModel 6 | { 7 | public IEnumerable Data { get; set; } 8 | public int TotalCount { get; set; } 9 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/HelperClasses/Streams/AudioStreamViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.HelperClasses.Streams; 2 | 3 | public class AudioStreamViewModel 4 | { 5 | public string Id { get; set; } 6 | public int? BitRate { get; set; } 7 | public string ChannelLayout { get; set; } 8 | public int? Channels { get; set; } 9 | public string Codec { get; set; } 10 | public string Language { get; set; } 11 | public int? SampleRate { get; set; } 12 | public bool IsDefault { get; set; } 13 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/HelperClasses/Streams/MediaSourceViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.HelperClasses.Streams; 2 | 3 | public class MediaSourceViewModel 4 | { 5 | public string Id { get; set; } 6 | public int? BitRate { get; set; } 7 | public string Container { get; set; } 8 | public string Path { get; set; } 9 | public string Protocol { get; set; } 10 | public long? RunTimeTicks { get; set; } 11 | public double SizeInMb { get; set; } 12 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/HelperClasses/Streams/MoviePersonViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.HelperClasses.Streams; 2 | 3 | class MoviePersonViewModel 4 | { 5 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/HelperClasses/Streams/SubtitleStreamViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.HelperClasses.Streams; 2 | 3 | public class SubtitleStreamViewModel 4 | { 5 | public string Id { get; set; } 6 | public string Codec { get; set; } 7 | public string DisplayTitle { get; set; } 8 | public bool IsDefault { get; set; } 9 | public string Language { get; set; } 10 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/HelperClasses/Streams/VideoStreamViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.HelperClasses.Streams; 2 | 3 | public class VideoStreamViewModel 4 | { 5 | public string Id { get; set; } 6 | public string AspectRatio { get; set; } 7 | public float? AverageFrameRate { get; set; } 8 | public int? BitRate { get; set; } 9 | public int? Channels { get; set; } 10 | public int? Height { get; set; } 11 | public string Language { get; set; } 12 | public int? Width { get; set; } 13 | public int? BitDepth { get; set; } 14 | public string Codec { get; set; } 15 | public bool IsDefault { get; set; } 16 | public string VideoRange { get; set; } 17 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/HelperClasses/TopCardViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.HelperClasses; 2 | 3 | public class TopCardViewModel 4 | { 5 | public string Title { get; set; } 6 | public string Unit { get; set; } 7 | public bool UnitNeedsTranslation { get; set; } 8 | public int ValueType { get; set; } 9 | public TopCardItemViewModel[] Values { get; set; } 10 | } 11 | 12 | public class TopCardItemViewModel 13 | { 14 | public string MediaId { get; set; } 15 | public string Image { get; set; } 16 | public string Label { get; set; } 17 | public string Value { get; set; } 18 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/HelperClasses/UserMediaViewViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmbyStat.Controllers.HelperClasses; 4 | 5 | public class UserMediaViewViewModel 6 | { 7 | public string Id { get; set; } 8 | public string Primary { get; set; } 9 | public string Name { get; set; } 10 | public string ParentId { get; set; } 11 | public decimal? WatchedPercentage { get; set; } 12 | public double WatchedTime { get; set; } 13 | public DateTimeOffset StartedWatching { get; set; } 14 | public DateTimeOffset EndedWatching { get; set; } 15 | public string DeviceId { get; set; } 16 | public string DeviceLogo { get; set; } 17 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/Job/JobViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmbyStat.Controllers.Job; 4 | 5 | public class JobViewModel 6 | { 7 | public int State { get; set; } 8 | public double? CurrentProgressPercentage { get; set; } 9 | public Guid Id { get; set; } 10 | public string StartTimeUtcIso { get; set; } 11 | public string EndTimeUtcIso { get; set; } 12 | public string Title { get; set; } 13 | public string Description { get; set; } 14 | public string Trigger { get; set; } 15 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/Log/LogFileViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.Log; 2 | 3 | public class LogFileViewModel 4 | { 5 | public string Name { get; set; } 6 | public long Size { get; set; } 7 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/MediaServer/LoginViewModel.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Enums; 2 | 3 | namespace EmbyStat.Controllers.MediaServer; 4 | 5 | public class LoginViewModel 6 | { 7 | public string ApiKey { get; set; } 8 | public string Address { get; set; } 9 | public ServerType Type { get; set; } 10 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/MediaServer/MediaServerLibraryViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.MediaServer; 2 | 3 | public class MediaServerLibraryViewModel 4 | { 5 | public string Id { get; set; } 6 | public string Name { get; set; } 7 | public string PrimaryImage { get; set; } 8 | public int Type { get; set; } 9 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/MediaServer/MediaServerUserRowViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmbyStat.Controllers.MediaServer; 4 | 5 | public class MediaServerUserRowViewModel 6 | { 7 | public string Id { get; set; } 8 | public string Name { get; set; } 9 | public DateTimeOffset? LastActivityDate { get; set; } 10 | public bool IsAdministrator { get; set; } 11 | public bool IsHidden { get; set; } 12 | public bool IsDisabled { get; set; } 13 | public int MovieViewCount { get; set; } 14 | public int EpisodeViewCount { get; set; } 15 | public int TotalViewCount { get; set; } 16 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/MediaServer/MediaServerUserStatisticsViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using EmbyStat.Controllers.HelperClasses; 3 | 4 | namespace EmbyStat.Controllers.MediaServer; 5 | 6 | public class MediaServerUserStatisticsViewModel 7 | { 8 | public List Cards { get; set; } 9 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/MediaServer/PluginViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.MediaServer; 2 | 3 | public class PluginViewModel 4 | { 5 | public string Id { get; set; } 6 | public string Name { get; set; } 7 | public string Version { get; set; } 8 | public string Description { get; set; } 9 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/MediaServer/StatusViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.MediaServer; 2 | 3 | public class EmbyStatusViewModel 4 | { 5 | public int MissedPings { get; set; } 6 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/MediaServer/UdpBroadcastViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.MediaServer; 2 | 3 | public class UdpBroadcastViewModel 4 | { 5 | public string Address { get; set; } 6 | public string Id { get; set; } 7 | public string Name { get; set; } 8 | public int Port { get; set; } 9 | public int Protocol { get; set; } 10 | public int Type { get; set; } 11 | public string BaseUrl { get; set; } 12 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/MediaServer/UrlViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.MediaServer; 2 | 3 | public class UrlViewModel 4 | { 5 | public string Url { get; set; } 6 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/MediaServer/UserIdViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.MediaServer; 2 | 3 | public class UserIdViewModel 4 | { 5 | public string Id { get; set; } 6 | public string Name { get; set; } 7 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/MediaServer/UserOverviewViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.MediaServer; 2 | 3 | public class UserOverviewViewModel 4 | { 5 | public string Id { get; set; } 6 | public string Name { get; set; } 7 | public bool IsAdministrator { get; set; } 8 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/Movie/MovieStatisticsViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using EmbyStat.Common.Models.Charts; 3 | using EmbyStat.Controllers.HelperClasses; 4 | 5 | namespace EmbyStat.Controllers.Movie; 6 | 7 | public class MovieStatisticsViewModel 8 | { 9 | public List Cards { get; set; } 10 | public List TopCards { get; set; } 11 | public List Charts { get; set; } 12 | public List Shorts { get; set; } 13 | public List NoImdb { get; set; } 14 | public List NoPrimary { get; set; } 15 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/Movie/ShortMovieViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.Movie; 2 | 3 | public class ShortMovieViewModel : SuspiciousMovieViewModel 4 | { 5 | public double Duration { get; set; } 6 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/Movie/SuspiciousMovieViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.Movie; 2 | 3 | public class SuspiciousMovieViewModel 4 | { 5 | public string MediaId { get; set; } 6 | public string Title { get; set; } 7 | public int Number { get; set; } 8 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/Movie/SuspiciousTablesViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace EmbyStat.Controllers.Movie; 4 | 5 | public class SuspiciousTablesViewModel 6 | { 7 | public List Shorts { get; set; } 8 | public List NoImdb { get; set; } 9 | public List NoPrimary { get; set; } 10 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/Settings/LanguageViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.Settings; 2 | 3 | public class LanguageViewModel 4 | { 5 | public string Id { get; set; } 6 | public string Name { get; set; } 7 | public string Code { get; set; } 8 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/Show/ShowChartsViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using EmbyStat.Controllers.HelperClasses; 3 | 4 | namespace EmbyStat.Controllers.Show; 5 | 6 | public class ShowChartsViewModel 7 | { 8 | public List BarCharts { get; set; } 9 | public List PieCharts { get; set; } 10 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/Show/ShowRowViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.Show; 2 | 3 | public class ShowRowViewModel 4 | { 5 | public string Id { get; set; } 6 | public string Name { get; set; } 7 | public string SortName { get; set; } 8 | public int SeasonCount { get; set; } 9 | public int EpisodeCount { get; set; } 10 | public int SpecialEpisodeCount { get; set; } 11 | public int MissingEpisodeCount { get; set; } 12 | public string Status { get; set; } 13 | public long? RunTime { get; set; } 14 | public long? CumulativeRunTime { get; set; } 15 | public string[] Genres { get; set; } 16 | public string OfficialRating { get; set; } 17 | public double SizeInMb { get; set; } 18 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/Show/ShowStatisticsViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using EmbyStat.Common.Models.Charts; 3 | using EmbyStat.Controllers.HelperClasses; 4 | 5 | namespace EmbyStat.Controllers.Show; 6 | 7 | public class ShowStatisticsViewModel 8 | { 9 | public List Cards { get; set; } 10 | public List TopCards { get; set; } 11 | public List BarCharts { get; set; } 12 | public List PieCharts { get; set; } 13 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/Show/VirtualEpisodeViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace EmbyStat.Controllers.Show; 5 | 6 | public class VirtualSeasonViewModel 7 | { 8 | public int IndexNumber { get; set; } 9 | public IEnumerable Episodes { get; set; } 10 | } 11 | 12 | public class VirtualEpisodeViewModel 13 | { 14 | public string Id { get; set; } 15 | public int IndexNumber { get; set; } 16 | public string Name { get; set; } 17 | public DateTime? PremiereDate { get; set; } 18 | } -------------------------------------------------------------------------------- /EmbyStat.Controllers/System/UpdateResultViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Controllers.System; 2 | 3 | public class UpdateResultViewModel 4 | { 5 | public bool IsUpdateAvailable { get; set; } 6 | public string AvailableVersion { get; set; } 7 | } -------------------------------------------------------------------------------- /EmbyStat.Core/About/AboutModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Core.About; 2 | 3 | public class AboutModel 4 | { 5 | public string OperatingSystem { get; set; } 6 | public string OperatingSystemVersion { get; set; } 7 | public string Architecture { get; set; } 8 | } -------------------------------------------------------------------------------- /EmbyStat.Core/About/AboutService.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Core.About.Interfaces; 2 | using Microsoft.DotNet.PlatformAbstractions; 3 | 4 | namespace EmbyStat.Core.About; 5 | 6 | public class AboutService : IAboutService 7 | { 8 | public AboutModel GetAbout() 9 | { 10 | var operatingSystem = RuntimeEnvironment.OperatingSystem; 11 | var operatingSystemVersion = RuntimeEnvironment.OperatingSystemVersion; 12 | var architecture = RuntimeEnvironment.RuntimeArchitecture; 13 | 14 | return new AboutModel { 15 | OperatingSystem = operatingSystem, 16 | OperatingSystemVersion = operatingSystemVersion, 17 | Architecture = architecture 18 | }; 19 | } 20 | } -------------------------------------------------------------------------------- /EmbyStat.Core/About/Interfaces/IAboutService.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Core.About.Interfaces; 2 | 3 | public interface IAboutService 4 | { 5 | AboutModel GetAbout(); 6 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Account/Interfaces/IAccountService.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Account; 2 | 3 | namespace EmbyStat.Core.Account.Interfaces; 4 | 5 | public interface IAccountService 6 | { 7 | Task Authenticate(AuthenticateRequest login, string remoteIp); 8 | Task Register(AuthenticateRequest login); 9 | Task LogOut(); 10 | Task RefreshToken(string accessToken, string refreshToken, string remoteIp); 11 | Task AnyAdmins(); 12 | Task ResetPassword(string username); 13 | Task ChangePassword(ChangePasswordRequest request); 14 | Task ChangeUserName(ChangeUserNameRequest request); 15 | Task CreateRoles(); 16 | } -------------------------------------------------------------------------------- /EmbyStat.Core/DataStore/ISqliteBootstrap.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Data.Sqlite; 2 | 3 | namespace EmbyStat.Core.DataStore; 4 | 5 | public interface ISqliteBootstrap 6 | { 7 | SqliteConnection CreateConnection(); 8 | } -------------------------------------------------------------------------------- /EmbyStat.Core/DataStore/Seeds/MediaServerSeed.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Entities; 2 | 3 | namespace EmbyStat.Core.DataStore.Seeds; 4 | 5 | public static class MediaServerSeed 6 | { 7 | public static readonly MediaServerStatus Status = new() {Id = new Guid("e55668a1-6a81-47ba-882d-738347e7e9cd"), MissedPings = 0}; 8 | } -------------------------------------------------------------------------------- /EmbyStat.Core/DataStore/SqliteBootstrap.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Configuration.Interfaces; 2 | using Microsoft.Data.Sqlite; 3 | 4 | namespace EmbyStat.Core.DataStore; 5 | 6 | public class SqliteBootstrap : ISqliteBootstrap 7 | { 8 | private readonly string _connectionString; 9 | public SqliteBootstrap(IConfigurationService configurationService) 10 | { 11 | var config = configurationService.Get(); 12 | var path = Path.Combine(config.SystemConfig.Dirs.Data, "SqliteData.db"); 13 | _connectionString = $"Data Source={path}"; 14 | } 15 | 16 | 17 | public SqliteConnection CreateConnection() 18 | { 19 | return new SqliteConnection(_connectionString); 20 | } 21 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Disk/DiskProvider.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Core.Disk.Interfaces; 2 | 3 | namespace EmbyStat.Core.Disk 4 | { 5 | public class DiskProvider : IDiskProvider 6 | { 7 | public string[] GetFiles(string path, SearchOption searchOption) 8 | { 9 | return Directory.GetFiles(path, "*.*", searchOption); 10 | } 11 | 12 | public string ReadAllText(string filePath) 13 | { 14 | return File.ReadAllText(filePath); 15 | } 16 | 17 | public bool FolderExists(string path) 18 | { 19 | return Directory.Exists(path); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /EmbyStat.Core/Disk/Interfaces/IDiskProvider.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Core.Disk.Interfaces; 2 | 3 | public interface IDiskProvider 4 | { 5 | string[] GetFiles(string path, SearchOption searchOption); 6 | string ReadAllText(string filePath); 7 | bool FolderExists(string path); 8 | } -------------------------------------------------------------------------------- /EmbyStat.Core/EnvironmentInfo/Interfaces/IOsInfo.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Core.EnvironmentInfo.Interfaces; 2 | 3 | public interface IOsInfo 4 | { 5 | string Version { get; } 6 | string Name { get; } 7 | string FullName { get; } 8 | bool IsDocker { get; } 9 | } -------------------------------------------------------------------------------- /EmbyStat.Core/EnvironmentInfo/Interfaces/IOsVersionAdapter.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Core.EnvironmentInfo.Interfaces; 2 | 3 | public interface IOsVersionAdapter 4 | { 5 | bool Enabled { get; } 6 | OsVersionModel Read(); 7 | } -------------------------------------------------------------------------------- /EmbyStat.Core/EnvironmentInfo/OsVersionModel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Core.EnvironmentInfo; 2 | 3 | public class OsVersionModel 4 | { 5 | public OsVersionModel(string name, string version, string fullName = null) 6 | { 7 | Name = Trim(name); 8 | Version = Trim(version); 9 | 10 | if (string.IsNullOrWhiteSpace(fullName)) 11 | { 12 | fullName = $"{Name} {Version}"; 13 | } 14 | 15 | FullName = Trim(fullName); 16 | } 17 | 18 | private static string Trim(string source) 19 | { 20 | return source.Trim().Trim('"', '\''); 21 | } 22 | 23 | public string Name { get; } 24 | public string FullName { get; } 25 | public string Version { get; } 26 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Filters/Interfaces/IFilterRepository.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Enums; 2 | using EmbyStat.Common.Models.Entities; 3 | 4 | namespace EmbyStat.Core.Filters.Interfaces; 5 | 6 | public interface IFilterRepository 7 | { 8 | Task Get(LibraryType type, string field); 9 | Task Insert(FilterValues values); 10 | Task DeleteAll(LibraryType type); 11 | Task DeleteAll(); 12 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Filters/Interfaces/IFilterService.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Enums; 2 | using EmbyStat.Common.Models.Entities; 3 | 4 | namespace EmbyStat.Core.Filters.Interfaces; 5 | 6 | public interface IFilterService 7 | { 8 | Task GetFilterValues(LibraryType type, string field); 9 | FilterValues CalculateFilterValues(LibraryType type, string field); 10 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Genres/Interfaces/IGenreRepository.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Entities; 2 | 3 | namespace EmbyStat.Core.Genres.Interfaces; 4 | 5 | public interface IGenreRepository 6 | { 7 | Task UpsertRange(IEnumerable genres); 8 | Task GetAll(); 9 | Task DeleteAll(); 10 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Hubs/EmbyStatHub.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.SignalR; 2 | 3 | namespace EmbyStat.Core.Hubs 4 | { 5 | public class EmbyStatHub : Hub 6 | { 7 | 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /EmbyStat.Core/Hubs/IHubHelper.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Tasks; 2 | using EmbyStat.Common.Models.Tasks.Enum; 3 | 4 | namespace EmbyStat.Core.Hubs; 5 | 6 | public interface IHubHelper 7 | { 8 | Task BroadcastJobProgress(JobProgress info); 9 | Task BroadcastJobLog(string jobName, string message, ProgressLogType type); 10 | Task BroadcastEmbyConnectionStatus(int missedPings); 11 | Task BroadcastUpdateState(bool isRunning); 12 | Task BroadcastUpdateFinished(bool successful); 13 | Task BroadcastResetLogLine(string line); 14 | Task BroadcastResetFinished(); 15 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Jobs/Interfaces/IJobRepository.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Entities; 2 | using EmbyStat.Common.Models.Tasks.Enum; 3 | 4 | namespace EmbyStat.Core.Jobs.Interfaces; 5 | 6 | public interface IJobRepository 7 | { 8 | IEnumerable GetAll(); 9 | Job? GetById(Guid id); 10 | Task StartJob(Guid id); 11 | Task EndJob(Guid id, DateTime endTime, JobState state); 12 | Task UpdateTrigger(Guid id, string trigger); 13 | Task ResetAllJobs(); 14 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Jobs/Interfaces/IJobService.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Entities; 2 | 3 | namespace EmbyStat.Core.Jobs.Interfaces; 4 | 5 | public interface IJobService 6 | { 7 | IEnumerable GetAll(); 8 | Job? GetById(Guid id); 9 | Task UpdateTrigger(Guid id, string trigger); 10 | Task ResetAllJobs(); 11 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Languages/Interfaces/ILanguageRepository.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Entities; 2 | 3 | namespace EmbyStat.Core.Languages.Interfaces; 4 | 5 | public interface ILanguageRepository 6 | { 7 | Task> GetLanguages(); 8 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Languages/Interfaces/ILanguageService.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Entities; 2 | 3 | namespace EmbyStat.Core.Languages.Interfaces; 4 | 5 | public interface ILanguageService 6 | { 7 | Task> GetLanguages(); 8 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Languages/LanguageRepository.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Entities; 2 | using EmbyStat.Core.DataStore; 3 | using EmbyStat.Core.Languages.Interfaces; 4 | using Microsoft.EntityFrameworkCore; 5 | 6 | namespace EmbyStat.Core.Languages; 7 | 8 | public class LanguageRepository : ILanguageRepository 9 | { 10 | private readonly EsDbContext _context; 11 | public LanguageRepository(EsDbContext context) 12 | { 13 | _context = context; 14 | } 15 | 16 | public Task> GetLanguages() 17 | { 18 | return _context.Languages.AsNoTracking().ToListAsync(); 19 | } 20 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Languages/LanguageService.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Entities; 2 | using EmbyStat.Core.Languages.Interfaces; 3 | 4 | namespace EmbyStat.Core.Languages; 5 | 6 | public class LanguageService : ILanguageService 7 | { 8 | private readonly ILanguageRepository _languageRepository; 9 | 10 | public LanguageService(ILanguageRepository languageRepository) 11 | { 12 | _languageRepository = languageRepository; 13 | } 14 | 15 | public Task> GetLanguages() 16 | { 17 | return _languageRepository.GetLanguages(); 18 | } 19 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Logging/Interfaces/ILogsService.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Core.Logging.Interfaces; 2 | 3 | public interface ILogService 4 | { 5 | IEnumerable GetLogFileList(); 6 | Task GetLogStream(string fileName, bool anonymous); 7 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Logging/LogFile.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Core.Logging; 2 | 3 | public class LogFile 4 | { 5 | public string Name { get; set; } 6 | public long Size { get; set; } 7 | } -------------------------------------------------------------------------------- /EmbyStat.Core/MediaServers/MediaServerUserStatistics.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Cards; 2 | 3 | namespace EmbyStat.Core.MediaServers; 4 | 5 | public class MediaServerUserStatistics 6 | { 7 | public List Cards { get; set; } 8 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Movies/Interfaces/IMovieService.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.DataGrid; 2 | using EmbyStat.Common.Models.Entities; 3 | using EmbyStat.Common.Models.Entities.Movies; 4 | using EmbyStat.Common.Models.Query; 5 | 6 | namespace EmbyStat.Core.Movies.Interfaces; 7 | 8 | public interface IMovieService 9 | { 10 | Task> GetMovieLibraries(); 11 | Task GetStatistics(); 12 | Task CalculateMovieStatistics(); 13 | bool TypeIsPresent(); 14 | Task> GetMoviePage(int skip, int take, string sortField, string sortOrder, Filter[] filters, bool requireTotalCount); 15 | Task GetMovie(string id); 16 | Task SetLibraryAsSynced(string[] libraryIds); 17 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Movies/MovieStatistics.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Cards; 2 | using EmbyStat.Common.Models.Charts; 3 | 4 | namespace EmbyStat.Core.Movies; 5 | 6 | public class MovieStatistics 7 | { 8 | public List Cards { get; set; } 9 | public List TopCards { get; set; } 10 | public List Charts { get; set; } 11 | public IEnumerable Shorts { get; set; } 12 | public IEnumerable NoImdb { get; set; } 13 | public IEnumerable NoPrimary { get; set; } 14 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Movies/ShortMovie.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Core.Movies; 2 | 3 | public class ShortMovie : SuspiciousMovie 4 | { 5 | public double Duration { get; set; } 6 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Movies/SuspiciousMovie.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Core.Movies; 2 | 3 | public class SuspiciousMovie 4 | { 5 | public string MediaId { get; set; } 6 | public string Title { get; set; } 7 | public int Number { get; set; } 8 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Movies/SuspiciousTables.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Core.Movies; 2 | 3 | public class SuspiciousTables 4 | { 5 | public IEnumerable Shorts { get; set; } 6 | public IEnumerable NoImdb { get; set; } 7 | public IEnumerable NoPrimary { get; set; } 8 | } -------------------------------------------------------------------------------- /EmbyStat.Core/People/Interfaces/IPersonRepository.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Entities; 2 | 3 | namespace EmbyStat.Core.People.Interfaces; 4 | 5 | public interface IPersonRepository 6 | { 7 | Task UpsertRange(IEnumerable people); 8 | Task DeleteAll(); 9 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Processes/Interfaces/IProcessProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Specialized; 2 | 3 | namespace EmbyStat.Core.Processes.Interfaces; 4 | 5 | public interface IProcessProvider 6 | { 7 | ProcessOutput StartAndCapture(string path, string args = null, StringDictionary environmentVariables = null); 8 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Processes/ProcessOutput.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Core.Processes; 2 | 3 | public class ProcessOutput 4 | { 5 | public int ExitCode { get; set; } 6 | public List Lines { get; set; } 7 | 8 | public ProcessOutput() 9 | { 10 | Lines = new List(); 11 | } 12 | 13 | public List Standard 14 | { 15 | get 16 | { 17 | return Lines.Where(c => c.Level == ProcessOutputLevel.Standard).ToList(); 18 | } 19 | } 20 | 21 | public List Error 22 | { 23 | get 24 | { 25 | return Lines.Where(c => c.Level == ProcessOutputLevel.Error).ToList(); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Processes/ProcessOutputLevel.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Core.Processes; 2 | 3 | public enum ProcessOutputLevel 4 | { 5 | Standard = 0, 6 | Error = 1 7 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Processes/ProcessOutputLine.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Core.Processes; 2 | 3 | public class ProcessOutputLine 4 | { 5 | public ProcessOutputLevel Level { get; set; } 6 | public string Content { get; set; } 7 | public DateTime Time { get; set; } 8 | 9 | public ProcessOutputLine(ProcessOutputLevel level, string content) 10 | { 11 | Level = level; 12 | Content = content; 13 | Time = DateTime.UtcNow; 14 | } 15 | 16 | public override string ToString() 17 | { 18 | return $"{Time} - {Level} - {Content}"; 19 | } 20 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Sessions/Interfaces/ISessionRepository.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Enums; 2 | using EmbyStat.Common.Models.Entities.Events; 3 | 4 | namespace EmbyStat.Core.Sessions.Interfaces; 5 | 6 | public interface ISessionRepository 7 | { 8 | IEnumerable GetMediaIdsForUser(string userId, MediaType type); 9 | IEnumerable GetSessionsForUser(string userId); 10 | int GetPlayCountForUser(string userId); 11 | Session GetSessionById(string sessionId); 12 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Sessions/Interfaces/ISessionService.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Enums; 2 | using EmbyStat.Common.Models.Entities.Events; 3 | 4 | namespace EmbyStat.Core.Sessions.Interfaces; 5 | 6 | public interface ISessionService 7 | { 8 | IEnumerable GetMediaIdsForUser(string id, MediaType type); 9 | IEnumerable GetSessionsForUser(string id); 10 | int GetPlayCountForUser(string id); 11 | void ProcessSessions(List sessions); 12 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Shows/Interfaces/IShowService.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.DataGrid; 2 | using EmbyStat.Common.Models.Entities; 3 | using EmbyStat.Common.Models.Entities.Shows; 4 | using EmbyStat.Common.Models.Query; 5 | 6 | namespace EmbyStat.Core.Shows.Interfaces; 7 | 8 | public interface IShowService 9 | { 10 | Task> GetShowLibraries(); 11 | Task GetStatistics(); 12 | Task CalculateShowStatistics(); 13 | bool TypeIsPresent(); 14 | Task> GetShowPage(int skip, int take, string sortField, string sortOrder, Filter[] filters, bool requireTotalCount); 15 | Task GetShow(string id); 16 | Task SetLibraryAsSynced(string[] libraryIds); 17 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Shows/ShowCharts.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Charts; 2 | 3 | namespace EmbyStat.Core.Shows; 4 | 5 | public class ShowCharts 6 | { 7 | public List BarCharts { get; set; } 8 | public List PieCharts { get; set; } 9 | 10 | public ShowCharts() 11 | { 12 | BarCharts = new List(); 13 | PieCharts = new List(); 14 | } 15 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Shows/ShowStatistics.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Cards; 2 | using EmbyStat.Common.Models.Charts; 3 | 4 | namespace EmbyStat.Core.Shows; 5 | 6 | public class ShowStatistics 7 | { 8 | public List Cards { get; set; } 9 | public List TopCards { get; set; } 10 | public List BarCharts { get; set; } 11 | public List PieCharts { get; set; } 12 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Statistics/Interfaces/IStatisticsRepository.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Enums; 2 | using EmbyStat.Common.Models.Entities; 3 | 4 | namespace EmbyStat.Core.Statistics.Interfaces; 5 | 6 | public interface IStatisticsRepository 7 | { 8 | Task GetLastResultByType(StatisticType type); 9 | Task ReplaceStatistic(string json, DateTime calculationDateTime, StatisticType type); 10 | Task DeleteStatistics(); 11 | Task MarkTypesAsInvalid(StatisticType type); 12 | } -------------------------------------------------------------------------------- /EmbyStat.Core/System/Interfaces/ISystemService.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Core.System.Interfaces; 2 | 3 | public interface ISystemService 4 | { 5 | Task ResetEmbyStatTables(); 6 | } -------------------------------------------------------------------------------- /EmbyStat.Core/Updates/Interfaces/IUpdateService.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Clients.GitHub.Models; 2 | 3 | namespace EmbyStat.Core.Updates.Interfaces; 4 | 5 | public interface IUpdateService 6 | { 7 | Task CheckForUpdate(); 8 | Task DownloadZipAsync(UpdateResult result); 9 | Task UpdateServerAsync(); 10 | } -------------------------------------------------------------------------------- /EmbyStat.Core/WebSockets/Interfaces/IWebSocketService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Hosting; 2 | 3 | namespace EmbyStat.Core.WebSockets.Interfaces; 4 | 5 | public interface IWebSocketService : IHostedService 6 | { 7 | 8 | } -------------------------------------------------------------------------------- /EmbyStat.Hosts.Cmd/ApplicationModes.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Hosts.Cmd; 2 | 3 | public enum ApplicationModes 4 | { 5 | Interactive, 6 | InstallService, 7 | UninstallService, 8 | Service, 9 | RegisterUrl, 10 | Migration 11 | } -------------------------------------------------------------------------------- /EmbyStat.Jobs/IBaseJob.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace EmbyStat.Jobs; 4 | 5 | public interface IBaseJob 6 | { 7 | Task Execute(); 8 | } -------------------------------------------------------------------------------- /EmbyStat.Jobs/IJobInitializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmbyStat.Jobs; 4 | 5 | public interface IJobInitializer 6 | { 7 | void Setup(bool canUpdate); 8 | void UpdateTrigger(Guid id, string trigger, bool canUpdate); 9 | } -------------------------------------------------------------------------------- /EmbyStat.Jobs/Jobs/Interfaces/ICheckUpdateJob.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Jobs.Jobs.Interfaces; 2 | 3 | public interface ICheckUpdateJob : IBaseJob 4 | { 5 | } -------------------------------------------------------------------------------- /EmbyStat.Jobs/Jobs/Interfaces/IDatabaseCleanupJob.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Jobs.Jobs.Interfaces; 2 | 3 | public interface IDatabaseCleanupJob : IBaseJob 4 | { 5 | } -------------------------------------------------------------------------------- /EmbyStat.Jobs/Jobs/Interfaces/IMovieSyncJob.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Jobs.Jobs.Interfaces; 2 | 3 | public interface IMovieSyncJob : IBaseJob 4 | { 5 | } -------------------------------------------------------------------------------- /EmbyStat.Jobs/Jobs/Interfaces/IPingEmbyJob.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Jobs.Jobs.Interfaces; 2 | 3 | public interface IPingEmbyJob : IBaseJob 4 | { 5 | } -------------------------------------------------------------------------------- /EmbyStat.Jobs/Jobs/Interfaces/IShowSyncJob.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Jobs.Jobs.Interfaces; 2 | 3 | public interface IShowSyncJob : IBaseJob 4 | { 5 | } -------------------------------------------------------------------------------- /EmbyStat.Jobs/Jobs/Interfaces/ISmallSyncJob.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Jobs.Jobs.Interfaces; 2 | 3 | public interface ISmallSyncJob : IBaseJob 4 | { 5 | } -------------------------------------------------------------------------------- /EmbyStat.Migrator/Interfaces/IMigration.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Configuration.Interfaces; 2 | 3 | namespace EmbyStat.Migrator.Interfaces; 4 | 5 | public interface IMigration 6 | { 7 | void MigrateUp(IConfigurationService configurationService, long version); 8 | } -------------------------------------------------------------------------------- /EmbyStat.Migrator/Interfaces/IMigrationRunner.cs: -------------------------------------------------------------------------------- 1 | namespace EmbyStat.Migrator.Interfaces; 2 | 3 | public interface IMigrationRunner 4 | { 5 | void Migrate(); 6 | } -------------------------------------------------------------------------------- /EmbyStat.Migrator/Interfaces/IMigrationSourceItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace EmbyStat.Migrator.Interfaces; 5 | 6 | public interface IMigrationSourceItem 7 | { 8 | IEnumerable MigrationTypeCandidates { get; } 9 | } -------------------------------------------------------------------------------- /EmbyStat.Migrator/Migrations/0001_CreateUserSettings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using EmbyStat.Common.Enums; 4 | using EmbyStat.Migrator.Models; 5 | 6 | namespace EmbyStat.Migrator.Migrations 7 | { 8 | [Migration(1)] 9 | public class DummyMigration : Migration 10 | { 11 | public override void Up() 12 | { 13 | //Dummy migrations 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /EmbyStat.Migrator/Models/AssemblyMigrationSourceItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using EmbyStat.Migrator.Interfaces; 6 | 7 | namespace EmbyStat.Migrator.Models; 8 | 9 | public class AssemblyMigrationSourceItem : IMigrationSourceItem 10 | { 11 | private readonly Assembly _assembly; 12 | 13 | public AssemblyMigrationSourceItem(Assembly assembly) 14 | { 15 | _assembly = assembly; 16 | } 17 | 18 | public IEnumerable MigrationTypeCandidates => _assembly.GetExportedTypes() 19 | .Where(t => typeof(IMigration).IsAssignableFrom(t) && !t.IsAbstract); 20 | } -------------------------------------------------------------------------------- /EmbyStat.Migrator/Models/Migration.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Configuration; 2 | using EmbyStat.Configuration.Interfaces; 3 | using EmbyStat.Migrator.Interfaces; 4 | 5 | namespace EmbyStat.Migrator.Models; 6 | 7 | public abstract class Migration : IMigration 8 | { 9 | protected Config Configuration { get; set; } 10 | protected IConfigurationService ConfigurationService { get; set; } 11 | public void MigrateUp(IConfigurationService configurationService, long version) 12 | { 13 | ConfigurationService = configurationService; 14 | Configuration = configurationService.Get(); 15 | Up(); 16 | 17 | Configuration.SystemConfig.Migration = version; 18 | configurationService.UpdateSystemConfiguration(Configuration.SystemConfig).Wait(); 19 | } 20 | 21 | public abstract void Up(); 22 | } -------------------------------------------------------------------------------- /EmbyStat.Migrator/Models/version.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EmbyStat.Migrator.Models; 4 | 5 | [AttributeUsage(AttributeTargets.Class, Inherited = false)] 6 | public class MigrationAttribute : Attribute 7 | { 8 | public readonly int Version; 9 | public MigrationAttribute(int version) 10 | { 11 | Version = version; 12 | } 13 | } -------------------------------------------------------------------------------- /EmbyStat.Migrator/ServiceCollectionMigratorExtention.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using EmbyStat.Migrator.Interfaces; 4 | using EmbyStat.Migrator.Models; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.DependencyInjection.Extensions; 7 | 8 | namespace EmbyStat.Migrator; 9 | 10 | public static class ServiceCollectionMigratorExtension 11 | { 12 | public static void AddJsonMigrator(this IServiceCollection services, Assembly assembly) 13 | { 14 | if (services == null) 15 | throw new ArgumentNullException(nameof(services)); 16 | 17 | services.TryAddSingleton(); 18 | services.TryAddSingleton(new AssemblyMigrationSourceItem(assembly)); 19 | } 20 | } -------------------------------------------------------------------------------- /EmbyStat.Web/.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "dotnet-ef": { 6 | "version": "3.1.3", 7 | "commands": [ 8 | "dotnet-ef" 9 | ] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.codeActionsOnSave": { 3 | "source.fixAll.eslint": true 4 | }, 5 | "eslint.validate": [ 6 | "javascript", 7 | "typescript" 8 | ], 9 | "files.eol": "\r\n" 10 | } -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/EmbyStat.Web/ClientApp/public/favicon.ico -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | EmbyStat 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "EmbyStat", 3 | "name": "EmbyStat server", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/public/runtime-config.js: -------------------------------------------------------------------------------- 1 | window.runConfig = { 2 | featureupvoteUrl: 'https://embystat.featureupvote.com/', 3 | githubUrl: 'https://github.com/mregni/EmbyStat/issues/new?template=Bug_report.md', 4 | crowdinUrl: 'https://crowdin.com/project/embystat', 5 | githubReleaseUrl: 'https://github.com/mregni/EmbyStat/releases', 6 | }; 7 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/authentication/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './requireAuth'; 2 | 3 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | margin: 0; 4 | padding: 0; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | 8 | font-size: 15px; 9 | } 10 | 11 | #root { 12 | min-height: 100vh; 13 | } 14 | 15 | p { 16 | margin: 0; 17 | } 18 | 19 | h4 { 20 | margin-bottom: 16px; 21 | } 22 | 23 | /* Disabling arrows in number text field 24 | /* Chrome, Safari, Edge, Opera */ 25 | input::-webkit-outer-spin-button, 26 | input::-webkit-inner-spin-button { 27 | -webkit-appearance: none; 28 | margin: 0; 29 | } 30 | 31 | /* Firefox */ 32 | input[type="number"] { 33 | -moz-appearance: textfield; 34 | } -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/about/hooks/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './useAbout'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/about/hooks/useAbout.tsx: -------------------------------------------------------------------------------- 1 | import {useCallback, useEffect, useState} from 'react'; 2 | 3 | import {About} from '../../../shared/models/about'; 4 | import {getAbout} from '../../../shared/services'; 5 | 6 | export const useAbout = () => { 7 | const [loaded, setLoaded] = useState(false); 8 | const [about, setAbout] = useState(null!); 9 | 10 | const load = useCallback(async () => { 11 | if (!loaded) { 12 | const result = await getAbout(); 13 | setAbout(result); 14 | setLoaded(true); 15 | } 16 | }, [loaded]); 17 | 18 | useEffect(() => { 19 | (async () => { 20 | await load(); 21 | })(); 22 | }, [load]); 23 | 24 | return {about, loaded}; 25 | }; 26 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/about/index.tsx: -------------------------------------------------------------------------------- 1 | export {About as default} from './About'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/home/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './home'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/jobs/JobList.tsx: -------------------------------------------------------------------------------- 1 | import React, {useContext} from 'react'; 2 | 3 | import {Stack} from '@mui/material'; 4 | 5 | import {JobsContext} from '../../shared/context/jobs'; 6 | import {Job} from '../../shared/models/jobs'; 7 | import {JobItem} from './JobItem'; 8 | 9 | export function JobList() { 10 | const {jobs} = useContext(JobsContext); 11 | 12 | return ( 13 | 14 | {jobs.map((job: Job, i: number) => ())} 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/jobs/Jobs.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import {Grid} from '@mui/material'; 4 | 5 | import {JobList} from './JobList'; 6 | import {JobLogs} from './JobLogs'; 7 | 8 | export function Jobs() { 9 | return ( 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/jobs/index.tsx: -------------------------------------------------------------------------------- 1 | export {Jobs as default} from './Jobs'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/login/index.tsx: -------------------------------------------------------------------------------- 1 | export {Login as default} from './Login'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/logs/index.tsx: -------------------------------------------------------------------------------- 1 | export {Logs as default} from './Logs'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/movies/List.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import {Stack} from '@mui/material'; 4 | 5 | import {EsTitle} from '../../shared/components/esTitle'; 6 | import {EsFilterContainer} from '../../shared/components/filter'; 7 | import {MoviesContext} from '../../shared/context/movies'; 8 | import {movieFilters} from './MovieFilters'; 9 | import {MovieTable} from './Table'; 10 | 11 | export function List() { 12 | return ( 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/movies/Table/Helpers/Body.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import {TableBody} from '@mui/material'; 4 | 5 | import {TablePage} from '../../../../shared/models/common'; 6 | import {MovieRow} from '../../../../shared/models/movie'; 7 | import {Row} from '.'; 8 | 9 | type BodyProps = { 10 | page: TablePage; 11 | } 12 | 13 | export function Body(props: BodyProps) { 14 | const {page} = props; 15 | 16 | return ( 17 | 18 | {page.data.map((row) => ())} 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/movies/Table/Helpers/DataLine.tsx: -------------------------------------------------------------------------------- 1 | import React, {ReactElement} from 'react'; 2 | import {useTranslation} from 'react-i18next'; 3 | 4 | import {Grid, Tooltip, Typography} from '@mui/material'; 5 | 6 | type DataLineProps = { 7 | icon: ReactElement; 8 | value: string | number; 9 | tooltip: string; 10 | } 11 | 12 | export function DataLine(props: DataLineProps) { 13 | const {icon, value, tooltip} = props; 14 | const {t} = useTranslation(); 15 | 16 | return ( 17 | 18 | 19 | 20 | {icon} 21 | 22 | 23 | 24 | {value} 25 | 26 | 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/movies/Table/Helpers/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './DataLine'; 2 | export * from './MultiString'; 3 | export * from './Body'; 4 | export * from './Row'; 5 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/movies/Table/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Table'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/movies/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './General'; 2 | export * from './Movies'; 3 | export * from './List'; 4 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/server/ServerInfo.tsx: -------------------------------------------------------------------------------- 1 | import React, {useContext} from 'react'; 2 | 3 | import {Stack} from '@mui/material'; 4 | 5 | import {ServerContext} from '../../shared/context/server'; 6 | import {EsServerDetails, EsServerExtraInfo, EsServerFeatures, EsServerPaths} from './components'; 7 | 8 | export function ServerInfo() { 9 | const {serverInfo} = useContext(ServerContext); 10 | 11 | if (serverInfo === null) { 12 | return (null); 13 | } 14 | 15 | return ( 16 | <> 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/server/components/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsServerDetails'; 2 | export * from './EsServerFeatures'; 3 | export * from './EsServerPaths'; 4 | export * from './EsServerExtraInfo'; 5 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/server/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Server'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/settings/Settings.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Outlet} from 'react-router'; 3 | 4 | type Props = {} 5 | 6 | export function Settings(props: Props) { 7 | return ( 8 | 9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/settings/components/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsUserCard'; 2 | export * from './EsPasswordCard'; 3 | export * from './EsLanguageCard'; 4 | export * from './EsTmdbApiCard'; 5 | export * from './EsRollbarCard'; 6 | export * from './EsMediaServerCard'; 7 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/settings/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Settings'; 2 | export * from './Server'; 3 | export * from './Shows'; 4 | export * from './Movies'; 5 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/shows/List.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import {Stack} from '@mui/material'; 4 | 5 | import {EsTitle} from '../../shared/components/esTitle'; 6 | import {EsFilterContainer} from '../../shared/components/filter'; 7 | import {ShowsContext} from '../../shared/context/shows'; 8 | import {showFilters} from './ShowFilters'; 9 | import {ShowTable} from './Table'; 10 | 11 | export function List() { 12 | return ( 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/shows/Table/Body.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import {TableBody} from '@mui/material'; 4 | 5 | import {TablePage} from '../../../shared/models/common'; 6 | import {ShowRow} from '../../../shared/models/show'; 7 | import {Row} from './Row'; 8 | 9 | type BodyProps = { 10 | page: TablePage; 11 | }; 12 | 13 | export function Body(props: BodyProps) { 14 | const {page} = props; 15 | 16 | return ( 17 | 18 | {page.data.map((row) => ())} 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/shows/Table/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Table'; 2 | export * from './useShowTable'; 3 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/shows/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Shows'; 2 | export * from './General'; 3 | export * from './List'; 4 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/users/components/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsUserTable'; 2 | export * from './EsUserStatistics'; 3 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/users/hooks/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './useUserTable'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/users/hooks/useUserDetails.tsx: -------------------------------------------------------------------------------- 1 | import {useState} from 'react'; 2 | 3 | import {MediaServerUserDetails} from '../../../shared/models/mediaServer'; 4 | import {getUserDetails} from '../../../shared/services'; 5 | 6 | export const useUserDetails = () => { 7 | const [loading, setLoading] = useState(true); 8 | const [userDetails, setUserDetails] = useState(null!); 9 | 10 | const fetchUserDetails = async (id: string | undefined) => { 11 | if (id !== undefined) { 12 | setLoading(true); 13 | const user = await getUserDetails(id); 14 | setUserDetails(user); 15 | setLoading(false); 16 | } 17 | }; 18 | 19 | return { 20 | loading, userDetails, fetchUserDetails, 21 | }; 22 | }; 23 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/users/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Users'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/users/subpages/components/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './User'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/users/subpages/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './UserDetails'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/wizard/Interfaces.tsx: -------------------------------------------------------------------------------- 1 | export interface LibraryStepProps { 2 | type: 'movie' | 'show'; 3 | } 4 | 5 | export interface ValidationHandle { 6 | validate: () => Promise; 7 | } 8 | 9 | export interface StepProps { 10 | handleNext?: () => void; 11 | } 12 | 13 | export interface ValidationHandleWithSave { 14 | saveChanges: () => void; 15 | validate: () => Promise; 16 | } 17 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/wizard/Steps/Helpers/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './ServerCard'; 2 | export * from './NewServerCard'; 3 | export * from './ServerCard'; 4 | export * from './TestSuccessFul'; 5 | export * from './TestFailed'; 6 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/wizard/Steps/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Intro'; 2 | export * from './UserDetails'; 3 | export * from './SearchMediaServer'; 4 | export * from './MediaServerDetails'; 5 | export * from './TestMediaServer'; 6 | export * from './ConfigureLibrary'; 7 | export * from './Finish'; 8 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/pages/wizard/index.tsx: -------------------------------------------------------------------------------- 1 | export {Wizard as default} from './Wizard'; 2 | export * from './Interfaces'; 3 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import {ReportHandler} from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({getCLS, getFID, getFCP, getLCP, getTTFB}) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/ara.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/bul.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/cat.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/cze.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/dan.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/dut.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/est.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/fin.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/fre.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/ger.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/hin.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/hun.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/ind.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/ita.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/jpn.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/lav.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/lit.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/pol.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/por.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/rum.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/rus.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/spa.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/swe.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/tha.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/ukr.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/icons/flags/vie.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/images/emby.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/EmbyStat.Web/ClientApp/src/shared/assets/images/emby.png -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/images/jellyfin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/EmbyStat.Web/ClientApp/src/shared/assets/images/jellyfin.png -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/images/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/EmbyStat.Web/ClientApp/src/shared/assets/images/logo-small.png -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/images/no-poster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/EmbyStat.Web/ClientApp/src/shared/assets/images/no-poster.png -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/images/running-logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/EmbyStat.Web/ClientApp/src/shared/assets/images/running-logo.gif -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/assets/images/under-construction.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/EmbyStat.Web/ClientApp/src/shared/assets/images/under-construction.webp -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/blockers/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsNoMedia'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/buttons/EsHyperLinkButton.tsx: -------------------------------------------------------------------------------- 1 | import {Button} from '@mui/material'; 2 | import React, {ReactElement} from 'react'; 3 | import OpenInNewIcon from '@mui/icons-material/OpenInNew'; 4 | 5 | type Props = { 6 | label: string; 7 | href: string; 8 | startIcon?: ReactElement; 9 | } 10 | 11 | export function EsHyperLinkButton(props: Props) { 12 | const {label, href, startIcon = } = props; 13 | return ( 14 | 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/buttons/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsSaveButton'; 2 | export * from './EsButton'; 3 | export * from './EsRoundIconButton'; 4 | export * from './EsHyperLinkButton'; 5 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/cards/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsBasicCard'; 2 | export * from './EsTopListCard'; 3 | export * from './EsSaveCard'; 4 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/charts/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsBarGraph'; 2 | export * from './EsPieChart'; 3 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esAppBar/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsAppBar'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esAvatar/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsAvatar'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esBoolCheck/EsBoolCheck.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'; 4 | import HighlightOffIcon from '@mui/icons-material/HighlightOff'; 5 | 6 | type Props = { 7 | value: boolean 8 | } 9 | 10 | export function EsBoolCheck(props: Props) { 11 | const {value} = props; 12 | 13 | return value ? 14 | : 15 | ; 16 | } 17 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esBoolCheck/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsBoolCheck'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esChipList/EsChipList.tsx: -------------------------------------------------------------------------------- 1 | import {Chip} from '@mui/material'; 2 | import React from 'react'; 3 | 4 | type Props = { 5 | list: string[]; 6 | maxItems?: number; 7 | } 8 | 9 | export function EsChipList(props: Props) { 10 | const {list, maxItems = 2} = props; 11 | return ( 12 | <> 13 | { 14 | list 15 | .slice(0, maxItems) 16 | .map((item) => ) 17 | } 18 | { 19 | list.length > maxItems ? 20 | : 21 | null 22 | } 23 | 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esChipList/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsChipList'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esDateOrNever/EsDateOrNever.tsx: -------------------------------------------------------------------------------- 1 | import {format} from 'date-fns'; 2 | import React from 'react'; 3 | import {useTranslation} from 'react-i18next'; 4 | 5 | import Typography from '@mui/material/Typography'; 6 | 7 | import {useLocale} from '../../hooks'; 8 | 9 | type Props = { 10 | value: string | null 11 | } 12 | 13 | export function EsDateOrNever(props: Props) { 14 | const {value} = props; 15 | const {locale} = useLocale(); 16 | const {t} = useTranslation(); 17 | 18 | return (value !== null ? 19 | {format(new Date(value), 'Pp', {locale})} : 20 | {t('COMMON.NEVER')} 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esDateOrNever/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsDateOrNever'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esFlag/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsFlag'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esFlagList/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsFlagList'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esLibrarySelector/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsLibrarySelector'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esLoading/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsLoading'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esMenuDrawer/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsMenuDrawer'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esPageLoader/EsPageLoader.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Grid from '@mui/material/Grid'; 4 | 5 | import LogoGif from '../../assets/images/running-logo.gif'; 6 | 7 | export function EsPageLoader() { 8 | return ( 9 | 18 | 19 | running logo 20 | 21 | 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esPageLoader/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsPageLoader'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esPoster/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsPoster'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esScrollbar/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsScrollbar'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esSortLabel/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsSortLabel'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esTextInput/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './esTextInput'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/esTitle/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsTitle'; 2 | export * from './EsChipTitle'; 3 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/filter/EsFilterChip.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import {Chip} from '@mui/material'; 4 | 5 | import {useFilterHelpers} from '../../hooks'; 6 | import {ActiveFilter} from '../../models/filter'; 7 | 8 | type FilterChipProps = { 9 | filter: ActiveFilter; 10 | removeFilter: (id: string) => void; 11 | } 12 | 13 | export function EsFilterChip(props: FilterChipProps) { 14 | const {filter, removeFilter} = props; 15 | const {generateLabel} = useFilterHelpers(); 16 | 17 | return ( removeFilter(filter.id)} 19 | label={generateLabel(filter)} 20 | variant="outlined" 21 | />); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/filter/EsFlagMenuItem.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import {Stack} from '@mui/material'; 4 | 5 | import {LabelValuePair} from '../../models/common'; 6 | import {EsFlag} from '../esFlag'; 7 | 8 | type EsFlagMenuItemprops = { 9 | item: LabelValuePair; 10 | } 11 | 12 | export function EsFlagMenuItem(props: EsFlagMenuItemprops) { 13 | const {item} = props; 14 | return ( 15 | 19 | 23 | {item.label} 24 | 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/filter/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './fields/EsFilterTextField'; 2 | export * from './EsNewFilterDialog'; 3 | export * from './EsFilterContainer'; 4 | export * from './fields/EsFilterNumberField'; 5 | export * from './fields/EsFilterRangeField'; 6 | export * from './fields/EsFilterDropdownField'; 7 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/table/EsFetchFailedRow.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | type Props = {} 4 | 5 | // TODO: implement this and also add to movie detail row 6 | export function EsFetchFailedRow(props: Props) { 7 | return ( 8 |
EsFetchFailedRow
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/table/Types.tsx: -------------------------------------------------------------------------------- 1 | export interface Header { 2 | label: string, 3 | field?: string, 4 | sortable?: boolean, 5 | width?: number | undefined, 6 | align?: 'right' | 'left', 7 | } 8 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/components/table/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './EsTableHeader'; 2 | export * from './Types'; 3 | export * from './EsTablePagination'; 4 | export * from './EsDetailRowSkeleton'; 5 | export * from './EsFetchFailedRow'; 6 | export * from './EsBoolRow'; 7 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/ILibraryContext.tsx: -------------------------------------------------------------------------------- 1 | import {ActiveFilter} from '../models/filter'; 2 | 3 | export interface LibraryContextProps { 4 | statistics: T; 5 | activeFilters: ActiveFilter[]; 6 | addFilter: (filter: ActiveFilter) => void; 7 | removeFilter: (id: string) => void; 8 | load: () => Promise; 9 | loaded: boolean; 10 | mediaPresent: boolean; 11 | } 12 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/jobs/JobContextProvider.tsx: -------------------------------------------------------------------------------- 1 | import React, {ReactElement} from 'react'; 2 | import {useJobsContext, JobsContext} from '.'; 3 | 4 | interface Props { 5 | children: ReactElement | ReactElement[]; 6 | } 7 | 8 | export function JobsContextProvider(props: Props): ReactElement { 9 | const {children} = props; 10 | const jobsContext = useJobsContext(); 11 | 12 | return ( 13 | 14 | {children} 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/jobs/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './JobContextProvider'; 2 | export * from './JobState'; 3 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/library/LibrariesContextProvider.tsx: -------------------------------------------------------------------------------- 1 | import React, {ReactElement} from 'react'; 2 | 3 | import {LibrariesContext, useLibrariesContext} from '.'; 4 | 5 | interface Props { 6 | children: ReactElement | ReactElement[]; 7 | } 8 | 9 | export function LibrariesContextProvider(props: Props): ReactElement { 10 | const {children} = props; 11 | const librariesContext = useLibrariesContext(); 12 | 13 | return ( 14 | 15 | {children} 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/library/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './LibrariesContextProvider'; 2 | export * from './LibrariesState'; 3 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/mediaServerUser/MediaServerUserContextProvider.tsx: -------------------------------------------------------------------------------- 1 | import React, {ReactElement} from 'react'; 2 | 3 | import {MediaServerUserContext, useMediaServerUserContext} from './MediaServerUserState'; 4 | 5 | interface Props { 6 | children: ReactElement | ReactElement[]; 7 | } 8 | 9 | export function MediaServerUserContextProvider(props: Props): ReactElement { 10 | const {children} = props; 11 | const context = useMediaServerUserContext(); 12 | 13 | return ( 14 | 15 | {children} 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/mediaServerUser/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './MediaServerUserContextProvider'; 2 | export * from './MediaServerUserState'; 3 | 4 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/movies/MoviesContextProvider.tsx: -------------------------------------------------------------------------------- 1 | import React, {ReactElement} from 'react'; 2 | 3 | import {MoviesContext, useMoviesContext} from './MoviesState'; 4 | 5 | interface Props { 6 | children: ReactElement | ReactElement[]; 7 | } 8 | 9 | export function MoviesContextProvider(props: Props): ReactElement { 10 | const {children} = props; 11 | const moviesContext = useMoviesContext(); 12 | 13 | return ( 14 | 15 | {children} 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/movies/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './MoviesContextProvider'; 2 | export * from './MoviesState'; 3 | 4 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/server/ServerContextProvider.tsx: -------------------------------------------------------------------------------- 1 | import React, {ReactElement} from 'react'; 2 | 3 | import {ServerContext, useServerContext} from '.'; 4 | 5 | interface Props { 6 | children: ReactElement | ReactElement[]; 7 | } 8 | 9 | export function ServerContextProvider(props: Props): ReactElement { 10 | const {children} = props; 11 | const serverContext = useServerContext(); 12 | 13 | return ( 14 | 15 | {children} 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/server/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './ServerContextProvider'; 2 | export * from './ServerState'; 3 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/settings/SettingsContextProvider.tsx: -------------------------------------------------------------------------------- 1 | import React, {ReactElement} from 'react'; 2 | import {useSettingsContext, SettingsContext} from '.'; 3 | 4 | interface Props { 5 | children: ReactElement | ReactElement[]; 6 | } 7 | 8 | export function SettingsContextProvider(props: Props): ReactElement { 9 | const {children} = props; 10 | const settingsContext = useSettingsContext(); 11 | 12 | return ( 13 | 14 | {children} 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/settings/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './SettingsState'; 2 | export * from './SettingsContextProvider'; 3 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/shows/ShowsContextProvider.tsx: -------------------------------------------------------------------------------- 1 | import React, {ReactElement} from 'react'; 2 | 3 | import {ShowsContext, useShowsContext} from '.'; 4 | 5 | interface Props { 6 | children: ReactElement | ReactElement[]; 7 | } 8 | 9 | export function ShowsContextProvider(props: Props): ReactElement { 10 | const {children} = props; 11 | const showsContext = useShowsContext(); 12 | 13 | return ( 14 | 15 | {children} 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/shows/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './ShowsContextProvider'; 2 | export * from './ShowsState'; 3 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/signalr/SignalRContextProvider.tsx: -------------------------------------------------------------------------------- 1 | import React, {ReactElement} from 'react'; 2 | 3 | type Props = { 4 | children: ReactElement | ReactElement[]; 5 | } 6 | 7 | export function SignalRContextProvider(props: Props) { 8 | const {children} = props; 9 | 10 | return ({children}); 11 | } 12 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/signalr/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './SignalRContextProvider'; 2 | export * from './SignalRState'; 3 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/user/UserContextProvider.tsx: -------------------------------------------------------------------------------- 1 | import React, {ReactElement} from 'react'; 2 | import {useUserContext, UserContext} from '.'; 3 | 4 | interface Props { 5 | children: ReactElement | ReactElement[]; 6 | } 7 | 8 | export function UserContextProvider(props: Props): ReactElement { 9 | const {children} = props; 10 | const userContext = useUserContext(); 11 | 12 | return ( 13 | 14 | {children} 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/user/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './UserState'; 2 | export * from './UserContextProvider'; 3 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/context/wizard/WizardContextProvider.tsx: -------------------------------------------------------------------------------- 1 | import React, {ReactElement} from 'react'; 2 | 3 | import {useWizardContext, WizardContext} from './WizardState'; 4 | 5 | interface Props { 6 | children: ReactElement | ReactElement[]; 7 | } 8 | 9 | export function WizardContextProvider(props: Props): ReactElement { 10 | const {children} = props; 11 | const wizardContext = useWizardContext(); 12 | 13 | return ( 14 | 15 | {children} 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/hooks/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './useServerType'; 2 | export * from './useLocale'; 3 | export * from './useEsLocation'; 4 | export * from './useMediaServerUrls'; 5 | export * from './useFilterHelpers'; 6 | export * from './useShowDetails'; 7 | export * from './useSearchMediaServers'; 8 | export * from './usePalette'; 9 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/hooks/useEsLocation.tsx: -------------------------------------------------------------------------------- 1 | import * as router from 'react-router-dom'; 2 | 3 | export interface RouteState { 4 | from: Location; 5 | } 6 | 7 | export function useEsLocation() { 8 | type L = router.Location & { state: RouteState }; 9 | return router.useLocation() as L; 10 | } 11 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/hooks/useShowDetails.tsx: -------------------------------------------------------------------------------- 1 | import {useState} from 'react'; 2 | 3 | import {Show} from '../models/common'; 4 | import {fetchShowDetails} from '../services/showService'; 5 | 6 | export const useShowDetails = () => { 7 | const [loading, setLoading] = useState(false); 8 | const [show, setShow] = useState(null!); 9 | 10 | const getShowDetails = (id: string): void => { 11 | if (!loading) { 12 | setLoading(true); 13 | fetchShowDetails(id) 14 | .then((show) => setShow(show)) 15 | .finally(() => setLoading(false)) 16 | .catch(() => setShow(null!)); 17 | } 18 | }; 19 | 20 | return {loading, show, getShowDetails}; 21 | }; 22 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/about/About.tsx: -------------------------------------------------------------------------------- 1 | export interface About { 2 | operatingSystem: string; 3 | operatingSystemVersion: string; 4 | architecture: string; 5 | } 6 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/about/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './About'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/common/Card.tsx: -------------------------------------------------------------------------------- 1 | export interface Card { 2 | title: string; 3 | value: string; 4 | type: 'text' | 'time' | 'size'; 5 | icon: string; 6 | } 7 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/common/Chart.tsx: -------------------------------------------------------------------------------- 1 | export interface Chart { 2 | title: string; 3 | SeriesCount: number; 4 | dataSets: SimpleData[]; 5 | } 6 | 7 | export interface SimpleData { 8 | label: string; 9 | value: number; 10 | } 11 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/common/LabelValuePair.tsx: -------------------------------------------------------------------------------- 1 | export interface LabelValuePair { 2 | label: string; 3 | value: string; 4 | } 5 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/common/TablePage.tsx: -------------------------------------------------------------------------------- 1 | export interface TablePage { 2 | data: T[]; 3 | totalCount: number; 4 | } 5 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/common/TopCard.tsx: -------------------------------------------------------------------------------- 1 | export interface TopCardItem { 2 | mediaId: string; 3 | image: string; 4 | label: string; 5 | value: string; 6 | } 7 | 8 | export interface TopCard { 9 | title: string; 10 | unit: string; 11 | unitNeedsTranslation: boolean; 12 | values: TopCardItem[]; 13 | valueType: number; 14 | } 15 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/common/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Chart'; 2 | export * from './Card'; 3 | export * from './TopCard'; 4 | export * from './Media'; 5 | export * from './TablePage'; 6 | export * from './LabelValuePair'; 7 | export * from './Color'; 8 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/filter/ActiveFilter.tsx: -------------------------------------------------------------------------------- 1 | import {FilterOperation} from '.'; 2 | 3 | export interface ActiveFilter { 4 | field: string; 5 | fieldLabel: string; 6 | fieldValue: string; 7 | operation: FilterOperation; 8 | value: string; 9 | id: string; 10 | } 11 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/filter/FilterConstants.tsx: -------------------------------------------------------------------------------- 1 | export const is = 'FILTERS.OPERATIONS.IS'; 2 | export const min = 'COMMON.MIN'; 3 | export const isNull = 'FILTERS.OPERATIONS.ISNULL'; 4 | export const has = 'FILTERS.OPERATIONS.HAS'; 5 | export const hasNo = 'FILTERS.OPERATIONS.HASNO'; 6 | export const between = 'FILTERS.OPERATIONS.BETWEEN'; 7 | export const isZero = 'FILTERS.OPERATIONS.ISZERO'; 8 | export const larger = 'FILTERS.OPERATIONS.LARGER'; 9 | export const smaller = 'FILTERS.OPERATIONS.SMALLER'; 10 | export const bit = 'COMMON.BIT'; 11 | export const pixels = 'COMMON.PIXELS'; 12 | export const fps = 'COMMON.FPS'; 13 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/filter/FilterValues.tsx: -------------------------------------------------------------------------------- 1 | import {LabelValuePair} from '../common'; 2 | 3 | export interface FilterValues { 4 | id: string; 5 | field: string; 6 | values: LabelValuePair[]; 7 | } 8 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/filter/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './ActiveFilter'; 2 | export * from './FilterDefinition'; 3 | export * from './FilterValues'; 4 | export * from './FilterConstants'; 5 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/jobs/JobLogLine.tsx: -------------------------------------------------------------------------------- 1 | export interface JobLogLine { 2 | value: string; 3 | type: number; 4 | jobName: string; 5 | dateTimeUtc: string; 6 | } 7 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/jobs/JobProgress.tsx: -------------------------------------------------------------------------------- 1 | export interface JobProgress { 2 | state: number; 3 | currentProgressPercentage: number; 4 | id: string; 5 | startTimeUtc: string; 6 | endTimeUtc: string; 7 | } 8 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/jobs/Jobs.tsx: -------------------------------------------------------------------------------- 1 | export interface Job { 2 | state: number; 3 | currentProgressPercentage: number; 4 | id: string; 5 | startTimeUtcIso: string; 6 | endTimeUtcIso: string; 7 | title: string; 8 | description: string; 9 | trigger: string; 10 | } 11 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/jobs/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Jobs'; 2 | export * from './JobLogLine'; 3 | export * from './JobProgress'; 4 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/language/Language.ts: -------------------------------------------------------------------------------- 1 | export interface Language { 2 | name: string; 3 | code: string; 4 | } 5 | 6 | export interface LanguageContainer { 7 | languages: Language[]; 8 | isLoaded: boolean; 9 | } 10 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/language/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Language'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/library/Library.tsx: -------------------------------------------------------------------------------- 1 | export interface Library { 2 | id: string; 3 | name: string; 4 | primary: string; 5 | type: number; 6 | syncType: number; 7 | sync: boolean; 8 | } 9 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/library/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Library'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/login/AuthenticateResponse.tsx: -------------------------------------------------------------------------------- 1 | export interface AuthenticateResponse { 2 | accessToken: string; 3 | refreshToken: string; 4 | } 5 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/login/JwtPayloadCustom.tsx: -------------------------------------------------------------------------------- 1 | import {JwtPayload} from 'jwt-decode'; 2 | 3 | export interface JwtPayloadCustom extends JwtPayload { 4 | roles: string[]; 5 | } 6 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/login/User.tsx: -------------------------------------------------------------------------------- 1 | export interface User { 2 | username: string; 3 | roles: string[]; 4 | } 5 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/login/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './AuthenticateResponse'; 2 | export * from './User'; 3 | export * from './JwtPayloadCustom'; 4 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/logs/LogFile.tsx: -------------------------------------------------------------------------------- 1 | export interface LogFile { 2 | name: string; 3 | size: number; 4 | } 5 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/logs/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './LogFile'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/mediaServer/MediaServer.tsx: -------------------------------------------------------------------------------- 1 | export interface MediaServer { 2 | address: string; 3 | apiKey: string; 4 | type: 0 | 1; 5 | name: string; 6 | id: string; 7 | } 8 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/mediaServer/MediaServerLogin.tsx: -------------------------------------------------------------------------------- 1 | export interface MediaServerLogin { 2 | apiKey: string; 3 | address: string; 4 | type: number; 5 | } 6 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/mediaServer/MediaServerPlugin.tsx: -------------------------------------------------------------------------------- 1 | export interface MediaServerPlugin { 2 | id: string; 3 | name: string; 4 | version: string; 5 | description: string; 6 | imageUrl: string; 7 | } 8 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/mediaServer/MediaServerUdpBroadcast.tsx: -------------------------------------------------------------------------------- 1 | export interface MediaServerUdpBroadcast { 2 | address: string; 3 | id: string; 4 | name: string; 5 | port: number; 6 | protocol: 0 | 1; 7 | type: 0 | 1; 8 | baseUrl: string; 9 | } 10 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/mediaServer/MediaServerUserRow.tsx: -------------------------------------------------------------------------------- 1 | export interface MediaServerUserRow { 2 | id: string; 3 | name: string; 4 | lastActivityDate: string | null; 5 | isAdministrator: boolean; 6 | isHidden: boolean; 7 | isDisabled: boolean; 8 | movieViewCount: number; 9 | episodeViewCount: number; 10 | totalViewCount: number; 11 | } 12 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/mediaServer/MediaServerUserStatistics.tsx: -------------------------------------------------------------------------------- 1 | import {Card} from '../common'; 2 | 3 | export interface MediaServerUserStatistics { 4 | cards: Card[]; 5 | } 6 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/mediaServer/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './MediaServerInfo'; 2 | export * from './MediaServerPlugin'; 3 | export * from './MediaServerUser'; 4 | export * from './MediaServerUdpBroadcast'; 5 | export * from './MediaServer'; 6 | export * from './MediaServerLogin'; 7 | export * from './MediaServerUserRow'; 8 | export * from './MediaServerUserStatistics'; 9 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/movie/Movie.tsx: -------------------------------------------------------------------------------- 1 | import {Video} from '../common'; 2 | 3 | export interface Movie extends Video { 4 | originalTitle: string; 5 | } 6 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/movie/MovieRow.tsx: -------------------------------------------------------------------------------- 1 | import {VideoStream} from '../common'; 2 | 3 | export interface MovieRow { 4 | id: string; 5 | name: string; 6 | container: string; 7 | subtitles: string[]; 8 | audioLanguages: string[]; 9 | imdb: string; 10 | tmdb: string; 11 | tvdb: string; 12 | runTime: number; 13 | officialRating: string; 14 | communityRating: number | null; 15 | genres: string[]; 16 | banner: string; 17 | logo: string; 18 | primary: string; 19 | thumb: string; 20 | sortName: string; 21 | path: string; 22 | premiereDate: Date | string | null; 23 | sizeInMb: number; 24 | videoStreams: VideoStream[]; 25 | } 26 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/movie/MovieStatistics.tsx: -------------------------------------------------------------------------------- 1 | import {Card, Chart, TopCard} from '../common'; 2 | 3 | export interface SuspiciousMovie { 4 | mediaId: string; 5 | title: string; 6 | number: number; 7 | } 8 | 9 | export interface ShortMovie { 10 | number: number; 11 | mediaId: string; 12 | title: string; 13 | duration: number; 14 | } 15 | 16 | export interface MovieStatistics { 17 | cards: Card[]; 18 | topCards: TopCard[]; 19 | charts: Chart[]; 20 | shorts: ShortMovie[]; 21 | noImdb: SuspiciousMovie[]; 22 | noPrimary: SuspiciousMovie[]; 23 | } 24 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/movie/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './MovieStatistics'; 2 | export * from './MovieRow'; 3 | export * from './Movie'; 4 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/settings/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Settings'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/show/ShowRow.tsx: -------------------------------------------------------------------------------- 1 | export interface ShowRow { 2 | id: string; 3 | name: string; 4 | sortName: string; 5 | status: string; 6 | seasonCount: number; 7 | episodeCount: number; 8 | specialEpisodeCount: number; 9 | missingEpisodeCount: number; 10 | runTime: number; 11 | cumulativeRunTime: number; 12 | genres: string[]; 13 | officialRating: string; 14 | sizeInMb: number; 15 | } 16 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/show/ShowStatistics.tsx: -------------------------------------------------------------------------------- 1 | import {Card, Chart, TopCard} from '../common'; 2 | 3 | export interface ShowStatistics { 4 | cards: Card[]; 5 | topCards: TopCard[]; 6 | barCharts: Chart[]; 7 | pieCharts: Chart[]; 8 | } 9 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/show/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './ShowStatistics'; 2 | export * from './ShowRow'; 3 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/user/User.tsx: -------------------------------------------------------------------------------- 1 | export interface User { 2 | username: string; 3 | } 4 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/user/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './User'; 2 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/wizard/Wizard.tsx: -------------------------------------------------------------------------------- 1 | import {Language} from '../language'; 2 | import {MediaServerInfo, MediaServerUdpBroadcast, MediaServerUser} from '../mediaServer'; 3 | 4 | export interface Wizard { 5 | serverName: string; 6 | apiKey: string; 7 | address: string; 8 | serverType: 0 | 1; 9 | serverId: string; 10 | userId: string; 11 | username: string; 12 | password: string; 13 | language: string; 14 | languages: Language[]; 15 | enableRollbarLogging: boolean; 16 | foundServers: MediaServerUdpBroadcast[]; 17 | searchedServers: boolean; 18 | movieLibraryIds: string[]; 19 | showLibraryIds: string[]; 20 | mediaServerInfo: MediaServerInfo; 21 | administrators: MediaServerUser[]; 22 | } 23 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/models/wizard/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Wizard'; 2 | 3 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/services/aboutService.tsx: -------------------------------------------------------------------------------- 1 | import {About} from '../models/about'; 2 | import {axiosInstance} from './axiosInstance'; 3 | 4 | const domain = 'about/'; 5 | 6 | export const getAbout = (): Promise => { 7 | return axiosInstance 8 | .get(domain) 9 | .then((response) => { 10 | return response.data; 11 | }); 12 | }; 13 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/services/filterService.tsx: -------------------------------------------------------------------------------- 1 | import {FilterValues} from '../models/filter'; 2 | import {axiosInstance} from './axiosInstance'; 3 | 4 | const domain = 'filter/'; 5 | 6 | export const getFilterValues = (filter: string | undefined): Promise => { 7 | return axiosInstance 8 | .get(`${domain}${filter}`) 9 | .then((response) => { 10 | return response.data; 11 | }); 12 | }; 13 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/services/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './settingsService'; 2 | export * from './jobService'; 3 | export * from './filterService'; 4 | export * from './jobService'; 5 | export * from './logService'; 6 | export * from './accountService'; 7 | export * from './serverService'; 8 | export * from './systemService'; 9 | export * from './aboutService'; 10 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/services/jobService.tsx: -------------------------------------------------------------------------------- 1 | import {axiosInstance} from './axiosInstance'; 2 | import {Job} from '../models/jobs'; 3 | 4 | const domain = 'job/'; 5 | 6 | export const getAllJobs = (): Promise => { 7 | return axiosInstance.get(domain).then((response) => response.data); 8 | }; 9 | 10 | export const fireJob = (id: string): Promise => { 11 | return axiosInstance.post(`${domain}fire/${id}`); 12 | }; 13 | 14 | export const updateTrigger = (id: string, cron: string): Promise => { 15 | return axiosInstance.patch(`${domain}${id}`, {}, {params: {cron}} ); 16 | }; 17 | 18 | export const getJobById = (id: string): Promise => { 19 | return axiosInstance.get(`${domain}${id}`).then((response) => response.data); 20 | }; 21 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/services/systemService.tsx: -------------------------------------------------------------------------------- 1 | import {axiosInstance} from './axiosInstance'; 2 | 3 | const domain = 'system/'; 4 | 5 | export const resetEmbyStat = (): Promise => { 6 | return axiosInstance 7 | .get(`${domain}reset`) 8 | .then((response) => { 9 | return response.data; 10 | }); 11 | }; 12 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/utils/calculateFileSize.tsx: -------------------------------------------------------------------------------- 1 | export const calculateFileSize = (value: number): string => { 2 | let suffix = 'MB'; 3 | if (value > 1073741824) { 4 | value /= 1073741824; 5 | suffix = 'PB'; 6 | } else if (value > 1048576) { 7 | value /= 1048576; 8 | suffix = 'TB'; 9 | } else if (value > 1024) { 10 | value /= 1024; 11 | suffix = 'GB'; 12 | } else { 13 | return `${value} ${suffix}`; 14 | } 15 | 16 | return `${value.toFixed(2)} ${suffix}`; 17 | }; 18 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/utils/customWindow.tsx: -------------------------------------------------------------------------------- 1 | export interface CustomWindow extends Window { 2 | runConfig: Config 3 | } 4 | 5 | export interface Config { 6 | featureupvoteUrl: string; 7 | githubUrl: string; 8 | crowdinUrl: string; 9 | githubReleaseUrl: string; 10 | } 11 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/utils/generateStreamChipLabel.tsx: -------------------------------------------------------------------------------- 1 | import {VideoStream} from '../models/common'; 2 | 3 | export const generateStreamChipLabel = (stream: VideoStream) => { 4 | const bitDepth = stream?.BitDepth !== undefined ? `${stream?.BitDepth}bit - ` : ''; 5 | return `${stream.height}x${stream.width} - 6 | ${+((stream.bitRate ?? 0) / 1048576).toFixed(2)}Mbps - 7 | ${bitDepth} ${stream.codec} - 8 | ${stream.videoRange}`; 9 | }; 10 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/utils/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './convertToIcon'; 2 | export * from './calculateFileSize'; 3 | export * from './generateStreamChipLabel'; 4 | export * from './jobIds'; 5 | export * from './customWindow'; 6 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/shared/utils/jobIds.tsx: -------------------------------------------------------------------------------- 1 | export const movieJobId = 'c40555dc-ea57-4c6e-a225-905223d31c3c'; 2 | export const showJobId = 'be68900b-ee1d-41ef-b12f-60ef3106052e'; 3 | -------------------------------------------------------------------------------- /EmbyStat.Web/ClientApp/src/tests/utils/calculateFileSize.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import {calculateFileSize} from '../../shared/utils'; 4 | 5 | const cases = [ 6 | [1, '1 MB'], 7 | [1024, '1024 MB'], 8 | [1025, '1.00 GB'], 9 | [4000, '3.91 GB'], 10 | [1048576, '1024.00 GB'], 11 | [1048577, '1.00 TB'], 12 | [4048577, '3.86 TB'], 13 | [1073741824, '1024.00 TB'], 14 | [1073741825, '1.00 PB'], 15 | [5073741825, '4.73 PB'], 16 | ]; 17 | 18 | describe('calculateFileSize utility', () => { 19 | it.each(cases)( 20 | 'given %p as argument, returns %p', 21 | (firstArg, expectedResult) => { 22 | const result = calculateFileSize(firstArg as number); 23 | expect(result).toEqual(expectedResult); 24 | }, 25 | ); 26 | }); 27 | -------------------------------------------------------------------------------- /EmbyStat.Web/EmbyStat.Web.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net6.0 4 | false 5 | AnyCPU;x64;x86 6 | 0.0.0.0 7 | 0.0.0.0 8 | 0.0.0.0 9 | {1D5D997D-34AE-45BE-9935-13E0D63EAC02} 10 | 11 | 12 | -------------------------------------------------------------------------------- /GitVersion.yml: -------------------------------------------------------------------------------- 1 | continuous-delivery-fallback-tag: '' 2 | branches: 3 | develop: 4 | regex: develop 5 | tag: 'dev' 6 | increment: Patch 7 | ignore: 8 | sha: [] 9 | -------------------------------------------------------------------------------- /Templates/unraid/unraid-blue-256px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/Templates/unraid/unraid-blue-256px.png -------------------------------------------------------------------------------- /Templates/unraid/unraid-blue-48px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/Templates/unraid/unraid-blue-48px.png -------------------------------------------------------------------------------- /Templates/unraid/unraid-blue-512px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/Templates/unraid/unraid-blue-512px.png -------------------------------------------------------------------------------- /Templates/unraid/unraid-blue-white_inside-256px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/Templates/unraid/unraid-blue-white_inside-256px.png -------------------------------------------------------------------------------- /Templates/unraid/unraid-blue-white_inside-48px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/Templates/unraid/unraid-blue-white_inside-48px.png -------------------------------------------------------------------------------- /Templates/unraid/unraid-blue-white_inside-512px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/Templates/unraid/unraid-blue-white_inside-512px.png -------------------------------------------------------------------------------- /Templates/unraid/unraid-white&blue-256px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/Templates/unraid/unraid-white&blue-256px.png -------------------------------------------------------------------------------- /Templates/unraid/unraid-white&blue-48px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/Templates/unraid/unraid-white&blue-48px.png -------------------------------------------------------------------------------- /Templates/unraid/unraid-white&blue-512px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/Templates/unraid/unraid-white&blue-512px.png -------------------------------------------------------------------------------- /Templates/unraid/unraid-white-256px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/Templates/unraid/unraid-white-256px.png -------------------------------------------------------------------------------- /Templates/unraid/unraid-white-48px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/Templates/unraid/unraid-white-48px.png -------------------------------------------------------------------------------- /Templates/unraid/unraid-white-512px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/Templates/unraid/unraid-white-512px.png -------------------------------------------------------------------------------- /Tests.Unit/Builders/DeviceBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EmbyStat.Common.Models.Entities; 3 | 4 | namespace Tests.Unit.Builders; 5 | 6 | public class DeviceBuilder 7 | { 8 | private readonly Device _device; 9 | 10 | public DeviceBuilder(string id) 11 | { 12 | _device = new Device 13 | { 14 | Id = id, 15 | Name = "deviceName", 16 | DateLastActivity = DateTime.Today.AddDays(-2) 17 | }; 18 | } 19 | 20 | public DeviceBuilder AddLastActivityDate(DateTime date) 21 | { 22 | _device.DateLastActivity = date; 23 | return this; 24 | } 25 | 26 | public Device Build() 27 | { 28 | return _device; 29 | } 30 | } -------------------------------------------------------------------------------- /Tests.Unit/Builders/FilterBuilder.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Query; 2 | 3 | namespace Tests.Unit.Builders; 4 | 5 | public class FilterBuilder 6 | { 7 | private readonly Filter filter; 8 | 9 | public FilterBuilder(string field, string operation, string value) 10 | { 11 | filter = new Filter 12 | { 13 | Field = field, 14 | Operation = operation, 15 | Value = value 16 | }; 17 | } 18 | 19 | public Filter Build() 20 | { 21 | return filter; 22 | } 23 | } -------------------------------------------------------------------------------- /Tests.Unit/Builders/MediaServerUserBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using MediaServerUser = EmbyStat.Common.Models.Entities.Users.MediaServerUser; 3 | 4 | namespace Tests.Unit.Builders; 5 | 6 | public class MediaServerUserBuilder 7 | { 8 | private readonly MediaServerUser _user; 9 | 10 | public MediaServerUserBuilder(string id) 11 | { 12 | _user = new MediaServerUser 13 | { 14 | Id = id, 15 | Name = "userName", 16 | LastActivityDate = DateTime.Today.AddDays(-2) 17 | }; 18 | } 19 | 20 | public MediaServerUserBuilder AddLastActivityDate(DateTime date) 21 | { 22 | _user.LastActivityDate = date; 23 | return this; 24 | } 25 | 26 | public MediaServerUser Build() 27 | { 28 | return _user; 29 | } 30 | } -------------------------------------------------------------------------------- /Tests.Unit/Builders/QueryResultBuilder.cs: -------------------------------------------------------------------------------- 1 | using MediaBrowser.Model.Dto; 2 | using MediaBrowser.Model.Querying; 3 | 4 | namespace Tests.Unit.Builders; 5 | 6 | public class QueryResultBuilder 7 | { 8 | private readonly QueryResult _result; 9 | 10 | public QueryResultBuilder(string name, string id) 11 | { 12 | _result = new QueryResult 13 | { 14 | Items = new[] 15 | { 16 | new BaseItemDto 17 | { 18 | Id = id, 19 | Name = name 20 | } 21 | }, 22 | TotalRecordCount = 1 23 | }; 24 | } 25 | 26 | public QueryResult Build() 27 | { 28 | return _result; 29 | } 30 | } -------------------------------------------------------------------------------- /Tests.Unit/Builders/SubtitleStreamBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EmbyStat.Common.Models.Entities.Streams; 3 | 4 | namespace Tests.Unit.Builders; 5 | 6 | public class SubtitleStreamBuilder 7 | { 8 | private readonly SubtitleStream _stream; 9 | 10 | public SubtitleStreamBuilder(string language) 11 | { 12 | _stream = new SubtitleStream 13 | { 14 | Language = language, 15 | Codec = "codec", 16 | DisplayTitle = language, 17 | Id = Guid.NewGuid().ToString(), 18 | IsDefault = false 19 | }; 20 | } 21 | public SubtitleStream Build() 22 | { 23 | return _stream; 24 | } 25 | } -------------------------------------------------------------------------------- /Tests.Unit/Builders/VideoStreamBuilder.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Models.Entities.Streams; 2 | 3 | namespace Tests.Unit.Builders; 4 | 5 | public class VideoStreamBuilder 6 | { 7 | private readonly VideoStream _stream; 8 | 9 | public VideoStreamBuilder() 10 | { 11 | _stream = new VideoStream 12 | { 13 | AverageFrameRate = 25, 14 | Height = 1000, 15 | Width = 1000, 16 | Codec = "h264", 17 | BitDepth = 8, 18 | VideoRange = "SDR" 19 | }; 20 | } 21 | 22 | public VideoStream Build() 23 | { 24 | return _stream; 25 | } 26 | } -------------------------------------------------------------------------------- /Tests.Unit/Extensions/DoubleExtensionTests.cs: -------------------------------------------------------------------------------- 1 | using EmbyStat.Common.Extensions; 2 | using FluentAssertions; 3 | using Xunit; 4 | 5 | namespace Tests.Unit.Extensions; 6 | 7 | public class DoubleExtensionTests 8 | { 9 | [Fact] 10 | public void FormatToDotDecimalString_Should_Return_String() 11 | { 12 | var value = 6.2d; 13 | var result = value.FormatToDotDecimalString(); 14 | result.Should().NotBeNull(); 15 | result.Should().Be("6.2"); 16 | } 17 | } -------------------------------------------------------------------------------- /Tests.Unit/Helpers/FakeRoleManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Identity; 3 | using Microsoft.Extensions.Logging; 4 | using Moq; 5 | 6 | namespace Tests.Unit.Helpers; 7 | 8 | public class FakeRoleManager : RoleManager 9 | { 10 | public FakeRoleManager() 11 | : base(new Mock>().Object, 12 | Array.Empty>(), 13 | new Mock().Object, 14 | new Mock().Object, 15 | new Mock>>().Object 16 | ) 17 | { 18 | } 19 | } -------------------------------------------------------------------------------- /Tests.Unit/Models/StartupOptionsTests.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using Xunit; 3 | using CommandLine; 4 | using EmbyStat.Common.Models; 5 | 6 | namespace Tests.Unit.Models; 7 | 8 | public class StartupOptionsTests 9 | { 10 | [Fact] 11 | public void Properties_Should_Be_Decorated_With_Option_Attribute() 12 | { 13 | typeof(StartupOptions) 14 | .Properties() 15 | .Should() 16 | .BeDecoratedWith(); 17 | } 18 | } -------------------------------------------------------------------------------- /Updater/nlog.config: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /branding/NSIS/install.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/branding/NSIS/install.ico -------------------------------------------------------------------------------- /branding/NSIS/installer-header.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/branding/NSIS/installer-header.bmp -------------------------------------------------------------------------------- /branding/NSIS/installer-header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/branding/NSIS/installer-header.png -------------------------------------------------------------------------------- /branding/NSIS/installer-right.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/branding/NSIS/installer-right.bmp -------------------------------------------------------------------------------- /branding/NSIS/installer-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/branding/NSIS/installer-right.png -------------------------------------------------------------------------------- /branding/NSIS/uninstall.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/branding/NSIS/uninstall.ico -------------------------------------------------------------------------------- /branding/logo-color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/branding/logo-color.png -------------------------------------------------------------------------------- /builds/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "**/*.yml": "azure-pipelines" 4 | } 5 | } -------------------------------------------------------------------------------- /builds/docker-containers/files/arm.dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/runtime:6.0-bullseye-slim-arm32v7 AS base 2 | LABEL author="UPing" 3 | LABEL maintainer="mikhael@uping.be" 4 | 5 | ENV LC_ALL=en_US.UTF-8 6 | ENV LANG=en_US.UTF-8 7 | ENV LANGUAGE=en_US.UTF-8 8 | ENV EMBYSTAT_LISTENURL=http://* 9 | ENV EMBYSTAT_PORT=6555 10 | 11 | WORKDIR /app 12 | COPY . . 13 | 14 | VOLUME /app/data 15 | EXPOSE 6555/tcp 16 | ENTRYPOINT ["dotnet", "EmbyStat.dll", "--data-dir", "/app/data"] 17 | -------------------------------------------------------------------------------- /builds/docker-containers/files/arm64.dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/runtime:6.0-bullseye-slim-arm64v8 AS base 2 | LABEL author="UPing" 3 | LABEL maintainer="mikhael@uping.be" 4 | 5 | ENV LC_ALL=en_US.UTF-8 6 | ENV LANG=en_US.UTF-8 7 | ENV LANGUAGE=en_US.UTF-8 8 | ENV EMBYSTAT_LISTENURL=http://* 9 | ENV EMBYSTAT_PORT=6555 10 | 11 | WORKDIR /app 12 | COPY . . 13 | 14 | VOLUME /app/data 15 | EXPOSE 6555/tcp 16 | ENTRYPOINT ["dotnet", "EmbyStat.dll", "--data-dir", "/app/data"] 17 | -------------------------------------------------------------------------------- /builds/docker-containers/files/linux.dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/runtime:6.0-bullseye-slim-amd64 AS base 2 | LABEL author="UPing" 3 | LABEL maintainer="mikhael@uping.be" 4 | 5 | ENV LC_ALL=en_US.UTF-8 6 | ENV LANG=en_US.UTF-8 7 | ENV LANGUAGE=en_US.UTF-8 8 | ENV EMBYSTAT_LISTENURL=http://* 9 | ENV EMBYSTAT_PORT=6555 10 | 11 | WORKDIR /app 12 | COPY . . 13 | 14 | VOLUME /app/data 15 | EXPOSE 6555/tcp 16 | ENTRYPOINT ["dotnet", "EmbyStat.dll", "--data-dir", "/app/data"] 17 | -------------------------------------------------------------------------------- /builds/docker-containers/files/manifest-beta.yaml: -------------------------------------------------------------------------------- 1 | image: uping/embystat:beta 2 | manifests: 3 | - 4 | image: uping/embystat:beta-win-x64 5 | platform: 6 | architecture: amd64 7 | os: windows 8 | - 9 | image: uping/embystat:beta-linux-x64 10 | platform: 11 | architecture: amd64 12 | os: linux -------------------------------------------------------------------------------- /builds/docker-containers/files/manifest-nightly.yaml: -------------------------------------------------------------------------------- 1 | image: uping/embystat:nightly 2 | manifests: 3 | - 4 | image: uping/embystat:nightly-win-x64 5 | platform: 6 | architecture: amd64 7 | os: windows 8 | - 9 | image: uping/embystat:nightly-linux-x64 10 | platform: 11 | architecture: amd64 12 | os: linux -------------------------------------------------------------------------------- /builds/docker-containers/files/manifest-tool-windows-amd64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mregni/EmbyStat/be617783dafaaa27d3a1b3524fbbc9fc9470795f/builds/docker-containers/files/manifest-tool-windows-amd64.exe -------------------------------------------------------------------------------- /builds/docker-containers/files/win.dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/runtime:6.0-nanoserver-ltsc2022 AS base 2 | LABEL author="UPing" 3 | LABEL maintainer="mikhael@uping.be" 4 | 5 | ENV EMBYSTAT_LISTENURL=http://* 6 | ENV EMBYSTAT_PORT=6555 7 | 8 | WORKDIR /app 9 | COPY . . 10 | 11 | VOLUME C:\\app\\data 12 | EXPOSE 6555/tcp 13 | ENTRYPOINT ["dotnet", "EmbyStat.dll", "--data-dir", "\\app\\data"] -------------------------------------------------------------------------------- /builds/scripts/rollbar.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [string]$rollbarKey, 3 | [string]$buildNumber 4 | ) 5 | 6 | $environment = "production" 7 | 8 | if($buildNumber -like '*dev*'){ 9 | $environment = "dev" 10 | } 11 | 12 | if($buildNumber -like '*beta*'){ 13 | $environment = "beta" 14 | } 15 | 16 | $postParams = @{ 17 | access_token="$rollbarKey"; 18 | environment="$environment"; 19 | revision="$buildNumber"; 20 | local_username="Mikhaël Regni"; 21 | status="succeeded" 22 | } 23 | Invoke-WebRequest -Uri https://api.rollbar.com/api/1/deploy -Method POST -UseBasicParsing -Body $postParams -------------------------------------------------------------------------------- /builds/templates/download.artifact.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: artifactName 3 | type: string 4 | - name: systemName 5 | type: string 6 | 7 | steps: 8 | - task: DownloadBuildArtifacts@1 9 | displayName: 'Download ${{ parameters.systemName }} Artifact' 10 | inputs: 11 | buildType: 'current' 12 | downloadType: 'single' 13 | artifactName: ${{ parameters.artifactName }} 14 | downloadPath: '$(System.ArtifactsDirectory)' -------------------------------------------------------------------------------- /builds/templates/npmbuild.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - script: 'npm install' 3 | displayName: 'Npm install' 4 | workingDirectory: 'EmbyStat.Web/ClientApp' 5 | 6 | - script: 'npm ${{ parameters.npmBuild }}' 7 | displayName: 'Build frontend' 8 | workingDirectory: 'EmbyStat.Web/ClientApp' 9 | 10 | - task: CopyFiles@2 11 | displayName: 'Copy frontend to publish folder' 12 | inputs: 13 | SourceFolder: 'EmbyStat.Web/ClientApp/build' 14 | Contents: '**' 15 | TargetFolder: 'publish/dist' -------------------------------------------------------------------------------- /builds/templates/sonarcloud.end.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - task: SonarCloudAnalyze@1 3 | displayName: 'Run Code Analysis' 4 | 5 | - task: SonarCloudPublish@1 6 | displayName: 'Publish Quality Gate Result' 7 | inputs: 8 | pollingTimeoutSec: '300' 9 | -------------------------------------------------------------------------------- /builds/templates/sonarcloud.start.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - task: SonarSource.sonarcloud.14d9cde6-c1da-4d55-aa01-2965cd301255.SonarCloudPrepare@1 3 | displayName: 'Prepare analysis on SonarCloud' 4 | inputs: 5 | SonarCloud: SonarCloud 6 | organization: 'd8c11b45-69cb-4181-8d1a-a2399df9f672' 7 | projectKey: '15579460-0cb2-4494-a9ed-ebcc05beeb00' 8 | projectVersion: '$(GitVersion.SemVer)' 9 | extraProperties: | 10 | sonar.exclusions=**/node_modules/**/*,**/*.js,**/*.css,**/*.spec.tsx,**/bin/**/*,**/*ViewModel.cs,**/EmbyStat.Common/Models/**,**/*.test.tsx -------------------------------------------------------------------------------- /builds/templates/update.version.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - task: VersionJSONFile@2 3 | displayName: 'Version package.json' 4 | inputs: 5 | Path: '$(Build.SourcesDirectory)' 6 | recursion: true 7 | VersionNumber: '$(GitVersion.AssemblySemVer)' 8 | useBuildNumberDirectly: False 9 | VersionRegex: '\d+\.\d+\.\d+\.\d+' 10 | versionForJSONFileFormat: '{1}.{2}.{3}' 11 | FilenamePattern: 'package.json' 12 | OutputVersion: 'OutputedVersion' 13 | 14 | - task: VersionDotNetCoreAssemblies@2 15 | displayName: 'Version .NET Core Assemblies' 16 | inputs: 17 | Path: '$(Build.SourcesDirectory)' 18 | VersionNumber: '$(GitVersion.AssemblySemVer)' 19 | Injectversion: False 20 | VersionRegex: '\d+\.\d+\.\d+\.\d+' 21 | FilenamePattern: '.csproj' 22 | OutputVersion: 'OutputedVersion' 23 | -------------------------------------------------------------------------------- /builds/ubuntu-x64/docker-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Builds the DEB inside the Docker container 4 | 5 | set -o errexit 6 | set -o xtrace 7 | 8 | # Move to source directory 9 | pushd ${SOURCE_DIR} 10 | 11 | # Remove build-dep for dotnet-sdk-3.1, since it's not a package in this image 12 | sed -i '/dotnet-sdk-3.1,/d' debian/control 13 | 14 | # Build DEB 15 | dpkg-buildpackage -us -uc 16 | 17 | # Move the artifacts out 18 | mkdir -p ${ARTIFACT_DIR}/deb 19 | mv /embystat[-_]* ${ARTIFACT_DIR}/deb/ 20 | chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR} -------------------------------------------------------------------------------- /builds/ubuntu-x64/pkg-src/changelog: -------------------------------------------------------------------------------- 1 | embystat (0.2-0) unstable; urgency=medium 2 | 3 | * Initial Release. 4 | 5 | -- root Tue, 04 Feb 2020 18:06:49 +0000 6 | -------------------------------------------------------------------------------- /builds/ubuntu-x64/pkg-src/compat: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /builds/ubuntu-x64/pkg-src/conf/embystat.service.conf: -------------------------------------------------------------------------------- 1 | # Jellyfin systemd configuration options 2 | 3 | # Use this file to override the user or environment file location. 4 | 5 | [Service] 6 | #User = embystat 7 | #EnvironmentFile = /etc/default/embystat -------------------------------------------------------------------------------- /builds/ubuntu-x64/pkg-src/control: -------------------------------------------------------------------------------- 1 | Source: embystat 2 | Section: net 3 | Priority: optional 4 | Maintainer: mregni 5 | Build-Depends: debhelper (>= 10), 6 | dotnet-sdk-3.1, 7 | npm | nodejs 8 | 9 | Standards-Version: 4.1.2 10 | Homepage: 11 | Vcs-Git: https://github.com/mregni/EmbyStat.git 12 | Vcs-Browser: https://github.com/mregni/EmbyStat 13 | Package: embystat 14 | Architecture: any 15 | Depends: ${shlibs:Depends}, ${misc:Depends} 16 | Description: Statistics website for Emby and Jellyfin 17 | This application calculates statistics from your Emby or Jellyfin server. 18 | It is written in C# for the .NET CORE 3.1 Platform. 19 | -------------------------------------------------------------------------------- /builds/ubuntu-x64/pkg-src/embystat.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Emby Stats program 3 | After=network.target 4 | 5 | [Service] 6 | User=embystat 7 | ExecStart=/usr/bin/embystat 8 | SuccessExitStatus=143 9 | TimeoutStopSec=10 10 | Restart=on-failure 11 | RestartSec=5 12 | 13 | [Install] 14 | WantedBy=multi-user.target 15 | -------------------------------------------------------------------------------- /builds/ubuntu-x64/pkg-src/embystat.upstart: -------------------------------------------------------------------------------- 1 | description "embystat daemon" 2 | 3 | start on (local-filesystems and net-device-up IFACE!=lo) 4 | stop on runlevel [!2345] 5 | 6 | console log 7 | respawn 8 | respawn limit 10 5 9 | 10 | kill timeout 20 11 | 12 | script 13 | set -x 14 | echo "Starting $UPSTART_JOB" 15 | 16 | # Log file 17 | logger -t "$0" "DEBUG: `set`" 18 | . /etc/default/embystat 19 | exec su -u $EMBYSTAT_USER -c /usr/bin/embystat $EMBYSTAT_ARGS 20 | end script 21 | -------------------------------------------------------------------------------- /builds/ubuntu-x64/pkg-src/gbp.conf: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | pristine-tar = False 3 | cleaner = fakeroot debian/rules clean 4 | 5 | [import-orig] 6 | filter = [ ".git*", ".hg*", ".vs*", ".vscode*" ] 7 | -------------------------------------------------------------------------------- /builds/ubuntu-x64/pkg-src/install: -------------------------------------------------------------------------------- 1 | usr/lib/embystat usr/lib/ 2 | debian/conf/embystat etc/default/ 3 | debian/conf/logging.json etc/embystat/ 4 | debian/conf/embystat.service.conf etc/systemd/system/embystat.service.d/ 5 | debian/conf/embystat-sudoers etc/sudoers.d/ 6 | debian/bin/restart.sh usr/lib/embystat/ 7 | -------------------------------------------------------------------------------- /builds/ubuntu-x64/pkg-src/po/POTFILES.in: -------------------------------------------------------------------------------- 1 | [type: gettext/rfc822deb] templates -------------------------------------------------------------------------------- /builds/ubuntu-x64/pkg-src/source/format: -------------------------------------------------------------------------------- 1 | 1.0 -------------------------------------------------------------------------------- /builds/ubuntu-x64/pkg-src/source/options: -------------------------------------------------------------------------------- 1 | tar-ignore='.git*' 2 | tar-ignore='**/.git' 3 | tar-ignore='**/.hg' 4 | tar-ignore='**/.vs' 5 | tar-ignore='**/.vscode' 6 | tar-ignore='builds' 7 | tar-ignore='**/bin' 8 | tar-ignore='**/obj' 9 | tar-ignore='**/.nuget' 10 | tar-ignore='*.deb' 11 | tar-ignore='ThirdParty' -------------------------------------------------------------------------------- /builds/windows-installer/helpers/ShowError.nsh: -------------------------------------------------------------------------------- 1 | ; Show error 2 | !macro ShowError TEXT RETRYLABEL 3 | MessageBox MB_ABORTRETRYIGNORE|MB_ICONSTOP "${TEXT}" IDIGNORE +2 IDRETRY ${RETRYLABEL} 4 | Abort 5 | !macroend 6 | 7 | !macro ShowErrorFinal TEXT 8 | MessageBox MB_OK|MB_ICONSTOP "${TEXT}" 9 | Abort 10 | !macroend -------------------------------------------------------------------------------- /commands.txt: -------------------------------------------------------------------------------- 1 | add migration: 2 | 3 | cd ./EmbyStat.Migrations 4 | dotnet ef migrations add AddLastUpdated --project ../EmbyStat.Repositories --startup-project ../EmbyStat.Web --output-dir Sqlite -------------------------------------------------------------------------------- /crowdin.yml: -------------------------------------------------------------------------------- 1 | files: 2 | - source: /EmbyStat.Web/ClientApp/public/locales/base.json 3 | translation: /EmbyStat.Web/ClientApp/public/locales/%locale%.json 4 | -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0-beta", 3 | "publicReleaseRefSpec": [ 4 | "^refs/heads/master$", 5 | "^refs/heads/v\\d+(?:\\.\\d+)?$" 6 | ], 7 | "cloudBuild": { 8 | "buildNumber": { 9 | "enabled": true 10 | } 11 | } 12 | } --------------------------------------------------------------------------------