From 2ea104c3a30b6b9134e3d8420b5ff0c7bccb27ab Mon Sep 17 00:00:00 2001 From: Florian Dupret <34862846+sephrat@users.noreply.github.com> Date: Mon, 3 Jan 2022 11:07:22 +0100 Subject: [PATCH 01/20] Remove obsolete PreDb option from Radarr settings Fixes #4450 --- src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.ts b/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.ts index dd702eae4..9e787b406 100644 --- a/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/radarr/radarr.component.ts @@ -62,7 +62,6 @@ export class RadarrComponent implements OnInit { { name: "Announced", value: "Announced" }, { name: "In Cinemas", value: "InCinemas" }, { name: "Physical / Web", value: "Released" }, - { name: "PreDb", value: "PreDb" }, ]; } From 2ccf3b7c82244212ce4fc7ac704f6df2dc2210ab Mon Sep 17 00:00:00 2001 From: contrib-readme-bot Date: Tue, 4 Jan 2022 10:39:42 +0000 Subject: [PATCH 02/20] chore: :busts_in_silhouette: Updated Contributors [skip ci] --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index efb5aade7..4e3b010ea 100644 --- a/README.md +++ b/README.md @@ -135,13 +135,6 @@ Here are some of the features Ombi has: Matt Jeanes - - - bernarden -
- Victor Usoltsev -
- sephrat @@ -149,6 +142,13 @@ Here are some of the features Ombi has: Sephrat + + + bernarden +
+ Victor Usoltsev +
+ dhruvb14 From 3dfb503ee7efb68513e8a8907e0af31faf50c0f4 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Tue, 4 Jan 2022 10:45:27 +0000 Subject: [PATCH 03/20] chore(release): :rocket: v4.8.1 --- CHANGELOG.md | 18 ++++-------------- version.json | 2 +- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b7c751921..3975133e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [4.8.1](https://github.com/Ombi-app/Ombi/compare/v4.8.0...v4.8.1) (2022-01-04) + + + # [4.8.0](https://github.com/Ombi-app/Ombi/compare/v4.7.11...v4.8.0) (2021-12-22) @@ -177,17 +181,3 @@ -# [4.4.0](https://github.com/Ombi-app/Ombi/compare/v4.3.2...v4.4.0) (2021-11-06) - - -### Bug Fixes - -* **request-list:** :bug: Fixed an issue where the request options were not appearing for Music requests ([c0406a2](https://github.com/Ombi-app/Ombi/commit/c0406a2ddebafb03d98ed25cdf7d89dc9a600c7d)) - - -### Features - -* **mass-email:** :sparkles: Added the ability to configure the Mass Email, we can now send BCC and we are less likely to be rate limited when not using bcc [#4377](https://github.com/Ombi-app/Ombi/issues/4377) ([ca655ae](https://github.com/Ombi-app/Ombi/commit/ca655ae57042dec44106a2f2ef5ba2e6f1019ee4)) - - - diff --git a/version.json b/version.json index 55bd633f6..0cf3a9a65 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.8.0" + "version": "4.8.1" } \ No newline at end of file From 40af6593b668d4712327c18f92f5b7b5a0a65e26 Mon Sep 17 00:00:00 2001 From: maartenheebink Date: Wed, 5 Jan 2022 11:11:11 +0100 Subject: [PATCH 04/20] feat(customization): :sparkles: Added possibility for custom favicons --- .../Settings/Models/CustomizationSettings.cs | 1 + src/Ombi/ClientApp/src/app/app.component.ts | 13 ++++++++++--- src/Ombi/ClientApp/src/app/interfaces/ISettings.ts | 3 ++- .../customization/customization.component.html | 9 +++++++++ src/Ombi/ClientApp/src/index.html | 4 ++-- src/Ombi/Views/Shared/_Layout.cshtml | 6 ++++++ 6 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/Ombi.Settings/Settings/Models/CustomizationSettings.cs b/src/Ombi.Settings/Settings/Models/CustomizationSettings.cs index 1f2155331..c8406493f 100644 --- a/src/Ombi.Settings/Settings/Models/CustomizationSettings.cs +++ b/src/Ombi.Settings/Settings/Models/CustomizationSettings.cs @@ -12,6 +12,7 @@ public bool RecentlyAddedPage { get; set; } public bool UseCustomPage { get; set; } public bool HideAvailableFromDiscover { get; set; } + public string Favicon { get; set; } public string AddToUrl(string part) { diff --git a/src/Ombi/ClientApp/src/app/app.component.ts b/src/Ombi/ClientApp/src/app/app.component.ts index cbfcf0af0..2c543606b 100644 --- a/src/Ombi/ClientApp/src/app/app.component.ts +++ b/src/Ombi/ClientApp/src/app/app.component.ts @@ -1,4 +1,4 @@ -import { OverlayContainer } from '@angular/cdk/overlay'; +import { OverlayContainer } from '@angular/cdk/overlay'; import { Component, OnInit, HostBinding, Inject } from "@angular/core"; import { NavigationStart, Router } from "@angular/router"; @@ -34,6 +34,7 @@ export class AppComponent implements OnInit { public userName: string; public userEmail: string; public accessToken: string; + public favicon: string; private hubConnected: boolean; @@ -88,9 +89,15 @@ export class AppComponent implements OnInit { this.customizationFacade.settings$().subscribe(x => { this.customizationSettings = x; if (this.customizationSettings && this.customizationSettings.applicationName) { - this.applicationName = this.customizationSettings.applicationName; - this.document.getElementsByTagName('title')[0].innerText = this.applicationName; + this.applicationName = this.customizationSettings.applicationName; + this.document.getElementsByTagName('title')[0].innerText = this.applicationName; } + + if (this.customizationSettings && this.customizationSettings.favicon) { + this.favicon = this.customizationSettings.favicon; + this.document.getElementById('favicon').setAttribute('href', this.favicon); + } + if (this.customizationSettings && this.customizationSettings.customCss) { var dom = this.document.getElementsByTagName('head')[0]; var css = document.createElement("style"); diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts index c5dcaffc6..c7990215f 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts @@ -1,4 +1,4 @@ -import { ISettings } from "./ICommon"; +import { ISettings } from "./ICommon"; import { RequestLimitType } from "."; export interface IExternalSettings extends ISettings { @@ -193,6 +193,7 @@ export interface ICustomizationSettings extends ISettings { recentlyAddedPage: boolean; useCustomPage: boolean; hideAvailableFromDiscover: boolean; + favicon: string; } export interface IJobSettings { diff --git a/src/Ombi/ClientApp/src/app/settings/customization/customization.component.html b/src/Ombi/ClientApp/src/app/settings/customization/customization.component.html index b2168bb72..4c8bcecb6 100644 --- a/src/Ombi/ClientApp/src/app/settings/customization/customization.component.html +++ b/src/Ombi/ClientApp/src/app/settings/customization/customization.component.html @@ -34,6 +34,15 @@ + + The favicon url should be an externally accesible URL. Leave blank for default. + +
+ + Custom Favicon + + +
Hide Available Content On The Discover Page diff --git a/src/Ombi/ClientApp/src/index.html b/src/Ombi/ClientApp/src/index.html index e9c1ed486..4f7786647 100644 --- a/src/Ombi/ClientApp/src/index.html +++ b/src/Ombi/ClientApp/src/index.html @@ -1,12 +1,12 @@ - + - + diff --git a/src/Ombi/Views/Shared/_Layout.cshtml b/src/Ombi/Views/Shared/_Layout.cshtml index 5cee9c275..3cd9ccc56 100644 --- a/src/Ombi/Views/Shared/_Layout.cshtml +++ b/src/Ombi/Views/Shared/_Layout.cshtml @@ -23,6 +23,12 @@ appName = "Ombi"; } + var favicon = customization.Favicon; + if (string.IsNullOrEmpty(favicon)) + { + favicon = "images/favicon/favicon.ico"; + } + } From efe7845dcd2e64070f7ed9d2410c53c0069f9909 Mon Sep 17 00:00:00 2001 From: contrib-readme-bot Date: Wed, 5 Jan 2022 10:11:28 +0000 Subject: [PATCH 05/20] chore: :busts_in_silhouette: Updated Contributors [skip ci] --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4e3b010ea..7ed4e2dcc 100644 --- a/README.md +++ b/README.md @@ -730,6 +730,13 @@ Here are some of the features Ombi has: M4tta + + + maartenheebink +
+ maartenheebink +
+ masterhuck @@ -750,15 +757,15 @@ Here are some of the features Ombi has:
Tdorsey
- + + thegame3202
Mike
- - + zobe123 From 1a17da325d21578788a3c432a67d3efb67a46ded Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Wed, 5 Jan 2022 10:14:47 +0000 Subject: [PATCH 06/20] chore(release): :rocket: v4.9.0 --- CHANGELOG.md | 18 +++++++++--------- version.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3975133e3..d3ffebb10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# [4.9.0](https://github.com/Ombi-app/Ombi/compare/v4.8.1...v4.9.0) (2022-01-05) + + +### Features + +* **customization:** :sparkles: Added possibility for custom favicons ([40af659](https://github.com/Ombi-app/Ombi/commit/40af6593b668d4712327c18f92f5b7b5a0a65e26)) + + + ## [4.8.1](https://github.com/Ombi-app/Ombi/compare/v4.8.0...v4.8.1) (2022-01-04) @@ -172,12 +181,3 @@ -# [4.6.0](https://github.com/Ombi-app/Ombi/compare/v4.4.0...v4.6.0) (2021-11-09) - - -### Features - -* :sparkles: Upgrade Ombi to .NET 6 ([#4390](https://github.com/Ombi-app/Ombi/issues/4390)) ([719eb7d](https://github.com/Ombi-app/Ombi/commit/719eb7dbe37b3a72d264e2f670067518eef70694)), closes [#4392](https://github.com/Ombi-app/Ombi/issues/4392) - - - diff --git a/version.json b/version.json index 0cf3a9a65..a44547047 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.8.1" + "version": "4.9.0" } \ No newline at end of file From 2cf67bf9b849e61f767ac710a8c8ed3d446f4a60 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 11 Jan 2022 09:51:55 +0000 Subject: [PATCH 07/20] =?UTF-8?q?chore:=20=F0=9F=8C=90=20Translations=20Up?= =?UTF-8?q?date=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi/wwwroot/translations/bg.json | 7 +- src/Ombi/wwwroot/translations/cs.json | 435 ++++++++++++++++++++++++++ src/Ombi/wwwroot/translations/da.json | 7 +- src/Ombi/wwwroot/translations/de.json | 7 +- src/Ombi/wwwroot/translations/es.json | 7 +- src/Ombi/wwwroot/translations/fr.json | 17 +- src/Ombi/wwwroot/translations/hu.json | 13 +- src/Ombi/wwwroot/translations/it.json | 9 +- src/Ombi/wwwroot/translations/nl.json | 7 +- src/Ombi/wwwroot/translations/no.json | 7 +- src/Ombi/wwwroot/translations/pl.json | 7 +- src/Ombi/wwwroot/translations/pt.json | 401 ++++++++++++------------ src/Ombi/wwwroot/translations/ru.json | 7 +- src/Ombi/wwwroot/translations/sk.json | 7 +- src/Ombi/wwwroot/translations/sv.json | 7 +- src/Ombi/wwwroot/translations/zh.json | 7 +- 16 files changed, 731 insertions(+), 221 deletions(-) create mode 100644 src/Ombi/wwwroot/translations/cs.json diff --git a/src/Ombi/wwwroot/translations/bg.json b/src/Ombi/wwwroot/translations/bg.json index d0826a54b..9242cd30a 100644 --- a/src/Ombi/wwwroot/translations/bg.json +++ b/src/Ombi/wwwroot/translations/bg.json @@ -226,7 +226,12 @@ "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" - } + }, + "Notify": "Notify", + "RemoveNotification": "Remove Notifications", + "SuccessfulNotify": "You will now be notified for title {{title}}", + "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", + "CouldntNotify": "Couldn't notify title {{title}}" }, "Issues": { "Title": "Проблеми", diff --git a/src/Ombi/wwwroot/translations/cs.json b/src/Ombi/wwwroot/translations/cs.json new file mode 100644 index 000000000..b3234f471 --- /dev/null +++ b/src/Ombi/wwwroot/translations/cs.json @@ -0,0 +1,435 @@ +{ + "Login": { + "SignInButton": "Přihlásit se", + "UsernamePlaceholder": "Uživatelské jméno", + "PasswordPlaceholder": "Heslo", + "RememberMe": "Zapamatovat si mě", + "SignInWith": "Přihlásit se pomocí {{appName}}", + "SignInWithPlex": "Přihlásit se přes Plex", + "ForgottenPassword": "Zapomněli jste heslo?", + "Errors": { + "IncorrectCredentials": "Nesprávné uživatelské jméno nebo heslo" + } + }, + "Common": { + "ContinueButton": "Pokračovat", + "Available": "Dostupný", + "Approved": "Schváleno", + "Pending": "Čeká na vyřízení", + "PartiallyAvailable": "Částečně dostupné", + "Monitored": "Monitorováno", + "NotAvailable": "Není k dispozici", + "ProcessingRequest": "Zpracovávání žádosti", + "PendingApproval": "Čeká na schválení", + "RequestDenied": "Žádost zamítnuta", + "NotRequested": "Nevyžádáno", + "Requested": "Vyžádáno", + "Search": "Hledat", + "Request": "Žádost", + "Denied": "Zamítnuto", + "Approve": "Schválit", + "PartlyAvailable": "Částečně k dispozici", + "ViewDetails": "View Details", + "Errors": { + "Validation": "Please check your entered values" + }, + "Cancel": "Cancel", + "Submit": "Submit", + "Update": "Update", + "tvShow": "TV Show", + "movie": "Movie", + "album": "Album" + }, + "PasswordReset": { + "EmailAddressPlaceholder": "Email Address", + "ResetPasswordButton": "Reset Password" + }, + "LandingPage": { + "OnlineHeading": "Currently Online", + "OnlineParagraph": "The media server is currently online", + "PartiallyOnlineHeading": "Partially Online", + "PartiallyOnlineParagraph": "The media server is partially online.", + "MultipleServersUnavailable": "There are {{serversUnavailable}} servers offline out of {{totalServers}}.", + "SingleServerUnavailable": "There is {{serversUnavailable}} server offline out of {{totalServers}}.", + "OfflineHeading": "Currently Offline", + "OfflineParagraph": "The media server is currently offline.", + "CheckPageForUpdates": "Check this page for continuous site updates." + }, + "ErrorPages": { + "NotFound": "Page not found" + }, + "NavigationBar": { + "Discover": "Discover", + "Search": "Search", + "Requests": "Requests", + "UserManagement": "Users", + "Issues": "Issues", + "Vote": "Vote", + "Donate": "Donate!", + "DonateLibraryMaintainer": "Donate to Library Maintainer", + "DonateTooltip": "This is how I convince my wife to let me spend my spare time developing Ombi 😁", + "UpdateAvailableTooltip": "Update Available!", + "Settings": "Settings", + "Welcome": "Welcome {{username}}", + "UpdateDetails": "Update Details", + "Logout": "Logout", + "OpenMobileApp": "Open Mobile App", + "RecentlyAdded": "Recently Added", + "ChangeTheme": "Change Theme", + "Calendar": "Calendar", + "UserPreferences": "Preferences", + "FeatureSuggestion": "Features", + "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "Filter": { + "Movies": "Movies", + "TvShows": "TV Shows", + "Music": "Music", + "People": "People" + }, + "MorningWelcome": "Good morning!", + "AfternoonWelcome": "Good afternoon!", + "EveningWelcome": "Good evening!" + }, + "Search": { + "Title": "Search", + "Paragraph": "Want to watch something that is not currently available? No problem, just search for it below and request it!", + "MoviesTab": "Movies", + "TvTab": "TV Shows", + "MusicTab": "Music", + "AdvancedSearch": "You can fill in any of the below to discover new media. All of the results are sorted by popularity", + "AdvancedSearchHeader": "Advanced Search", + "Suggestions": "Suggestions", + "NoResults": "Sorry, we didn't find any results!", + "DigitalDate": "Digital Release: {{date}}", + "TheatricalRelease": "Theatrical Release: {{date}}", + "ViewOnPlex": "Play On Plex", + "ViewOnEmby": "Play On Emby", + "ViewOnJellyfin": "Play On Jellyfin", + "RequestAdded": "Request for {{title}} has been added successfully", + "Similar": "Similar", + "Refine": "Refine", + "SearchBarPlaceholder": "Type Here to Search", + "Movies": { + "PopularMovies": "Popular Movies", + "UpcomingMovies": "Upcoming Movies", + "TopRatedMovies": "Top Rated Movies", + "NowPlayingMovies": "Now Playing Movies", + "HomePage": "Home Page", + "Trailer": "Trailer" + }, + "TvShows": { + "Popular": "Popular", + "Trending": "Trending", + "MostWatched": "Most Watched", + "MostAnticipated": "Most Anticipated", + "Results": "Results", + "AirDate": "Air Date:", + "AllSeasons": "All Seasons", + "FirstSeason": "First Season", + "LatestSeason": "Latest Season", + "Select": "Select ...", + "SubmitRequest": "Submit Request", + "Season": "Season {{seasonNumber}}", + "SelectAllInSeason": "Select All in Season {{seasonNumber}}" + }, + "AdvancedSearchInstructions": "Please choose what type of media you are searching for:", + "YearOfRelease": "Year of Release", + "SearchGenre": "Search Genre", + "SearchKeyword": "Search Keyword", + "SearchProvider": "Search Provider", + "KeywordSearchingDisclaimer": "Please note that Keyword Searching is very hit and miss due to the inconsistent data in TheMovieDb" + }, + "Requests": { + "Title": "Requests", + "Paragraph": "Below you can see yours and all other requests, as well as their download and approval status.", + "MoviesTab": "Movies", + "ArtistName": "Artist", + "AlbumName": "Album Name", + "TvTab": "TV Shows", + "MusicTab": "Music", + "RequestedBy": "Requested By", + "Status": "Status", + "RequestStatus": "Request status", + "Denied": " Denied:", + "TheatricalRelease": "Theatrical Release: {{date}}", + "ReleaseDate": "Released: {{date}}", + "TheatricalReleaseSort": "Theatrical Release", + "DigitalRelease": "Digital Release: {{date}}", + "RequestDate": "Request Date", + "QualityOverride": "Quality Override:", + "RootFolderOverride": "Root Folder Override:", + "ChangeRootFolder": "Root Folder", + "ChangeQualityProfile": "Quality Profile", + "MarkUnavailable": "Mark Unavailable", + "MarkAvailable": "Mark Available", + "Remove": "Remove", + "Deny": "Deny", + "DenyReason": "Deny Reason", + "DeniedReason": "Denied Reason", + "Season": "Season", + "GridTitle": "Title", + "AirDate": "Air Date", + "GridStatus": "Status", + "ReportIssue": "Report Issue", + "Filter": "Filter", + "Sort": "Sort", + "SeasonNumberHeading": "Season: {seasonNumber}", + "SortTitleAsc": "Title ▲", + "SortTitleDesc": "Title ▼", + "SortRequestDateAsc": "Request Date ▲", + "SortRequestDateDesc": "Request Date ▼", + "SortStatusAsc": "Status ▲", + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} requests remaining", + "NextDays": "Another request will be added in {{time}} days", + "NextHours": "Another request will be added in {{time}} hours", + "NextMinutes": "Another request will be added in {{time}} minutes", + "NextMinute": "Another request will be added in {{time}} minute" + }, + "AllRequests": "All Requests", + "PendingRequests": "Pending Requests", + "ProcessingRequests": "Processing Requests", + "AvailableRequests": "Available Requests", + "DeniedRequests": "Denied Requests", + "RequestsToDisplay": "Requests to display", + "RequestsTitle": "Title", + "Details": "Details", + "Options": "Options", + "RequestPanel": { + "Delete": "Delete Request", + "Approve": "Approve Request", + "ChangeAvailability": "Mark Available", + "Deleted": "Successfully deleted selected items", + "Approved": "Successfully approved selected items" + }, + "SuccessfullyApproved": "Successfully Approved", + "SuccessfullyDeleted": "Request successfully deleted", + "NowAvailable": "Request is now available", + "NowUnavailable": "Request is now unavailable", + "SuccessfullyReprocessed": "Successfully Re-processed the request", + "DeniedRequest": "Denied Request", + "RequestCollection": "Request Collection", + "CollectionSuccesfullyAdded": "The collection {{name}} has been successfully added!", + "NeedToSelectEpisodes": "You need to select some episodes!", + "RequestAddedSuccessfully": "Request for {{title}} has been added successfully", + "ErrorCodes": { + "AlreadyRequested": "This has already been requested", + "EpisodesAlreadyRequested": "We already have episodes requested from this series", + "NoPermissionsOnBehalf": "You do not have the correct permissions to request on behalf of users!", + "NoPermissions": "You do not have the correct permissions!", + "RequestDoesNotExist": "Request does not exist", + "ChildRequestDoesNotExist": "Child Request does not exist", + "NoPermissionsRequestMovie": "You do not have permissions to Request a Movie", + "NoPermissionsRequestTV": "You do not have permissions to Request a TV Show", + "NoPermissionsRequestAlbum": "You do not have permissions to Request an Album", + "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", + "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", + "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" + }, + "Notify": "Notify", + "RemoveNotification": "Remove Notifications", + "SuccessfulNotify": "You will now be notified for title {{title}}", + "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", + "CouldntNotify": "Couldn't notify title {{title}}" + }, + "Issues": { + "Title": "Issues", + "IssuesForTitle": "Issues for {{title}}", + "PendingTitle": "Pending Issues", + "InProgressTitle": "In Progress Issues", + "ResolvedTitle": "Resolved Issues", + "ColumnTitle": "Title", + "Count": "Count", + "Category": "Category", + "Status": "Status", + "Details": "Details", + "Description": "Description", + "NoComments": "No Comments!", + "MarkInProgress": "Mark In Progress", + "MarkResolved": "Mark Resolved", + "SendMessageButton": "Send", + "Subject": "Subject", + "Comments": "Comments", + "WriteMessagePlaceholder": "Write your message here...", + "ReportedBy": "Reported By", + "IssueDialog": { + "Title": "Report an issue", + "DescriptionPlaceholder": "Please describe the issue", + "TitlePlaceholder": "Short title of your issue", + "SelectCategory": "Select Category", + "IssueCreated": "Issue has been created" + }, + "Outstanding": "There are outstanding issues", + "ResolvedDate": "Resolved date", + "CreatedDate": "Raised on", + "MarkedAsResolved": "This issue has now been marked as resolved!", + "MarkedAsInProgress": "This issue has now been marked as in progress!", + "Delete": "Delete issue", + "DeletedIssue": "Issue has been deleted", + "Chat": "Chat", + "EnterYourMessage": "Enter Your Message", + "Requested": "Requested", + "UserOnDate": "{{user}} on {{date}}" + }, + "Filter": { + "ClearFilter": "Clear Filter", + "FilterHeaderAvailability": "Availability", + "FilterHeaderRequestStatus": "Status", + "Approved": "Approved", + "PendingApproval": "Pending Approval", + "WatchProviders": "Watch Providers", + "Keywords": "Keywords" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} remaining", + "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", + "TvDue": "TV: {{date}}", + "MovieDue": "Movie: {{date}}", + "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" + }, + "MediaDetails": { + "Denied": "Denied", + "Trailers": "Trailers", + "RecommendationsTitle": "Recommendations", + "SimilarTitle": "Similar", + "VideosTitle": "Videos", + "AlbumsTitle": "Albums", + "RequestAllAlbums": "Request All Albums", + "ClearSelection": "Clear Selection", + "RequestSelectedAlbums": "Request Selected Albums", + "ViewCollection": "View Collection", + "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", + "AdvancedOptions": "Advanced Options", + "AutoApproveOptions": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! Please note, this is optional, just press Request to skip!", + "AutoApproveOptionsTv": "You can configure the request here, once requested it will be sent to your DVR application and will be auto approved! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", + "AutoApproveOptionsTvShort": "You can configure the request here, once requested it will be sent to your DVR application! If the request is already in Sonarr, we will not change the root folder or quality profile if you set it! Please note, this is optional, just press Request to skip!", + "QualityProfilesSelect": "Select A Quality Profile", + "RootFolderSelect": "Select A Root Folder", + "LanguageProfileSelect": "Select A Language Profile", + "Status": "Status:", + "StatusValues": { + "Rumored": "Rumored", + "Planned": "Planned", + "In Production": "In Production", + "Post Production": "Post Production", + "Released": "Released", + "Running": "Running", + "Returning Series": "Returning Series", + "Ended": "Ended", + "Canceled": "Canceled" + }, + "Seasons": "Seasons:", + "Episodes": "Episodes:", + "Availability": "Availability:", + "RequestStatus": "Request Status", + "Quality": "Quality:", + "RootFolderOverride": "Root Folder Override:", + "QualityOverride": "Quality Override:", + "Network": "Network:", + "GenresLabel": "Genres:", + "Genres": "Genres", + "FirstAired": "First Aired:", + "TheatricalRelease": "Release:", + "DigitalRelease": "Digital Release:", + "Votes": "Votes:", + "Runtime": "Runtime:", + "Minutes": "{{runtime}} Minutes", + "Revenue": "Revenue:", + "Budget": "Budget:", + "Keywords": "Keywords/Tags:", + "Casts": { + "CastTitle": "Cast" + }, + "EpisodeSelector": { + "AllSeasonsTooltip": "This will request every season for this show", + "FirstSeasonTooltip": "This will only request the First Season for this show", + "LatestSeasonTooltip": "This will only request the Latest Season for this show", + "NoEpisodes": "There unfortunately is no episode data for this show yet!", + "SeasonNumber": "Season {{number}}" + }, + "SonarrConfiguration": "Sonarr Configuration", + "RadarrConfiguration": "Radarr Configuration", + "RequestOnBehalf": "Request on behalf of", + "PleaseSelectUser": "Please select a user", + "StreamingOn": "Streaming On:", + "RequestedBy": "Requested By:", + "RequestedByOn": "Requested By {{user}} on {{date}}", + "RequestDate": "Request Date:", + "DeniedReason": "Denied Reason:", + "ReProcessRequest": "Re-Process Request", + "Music": { + "Type": "Type:", + "Country": "Country:", + "StartDate": "Start Date:", + "EndDate": "EndDate:" + } + }, + "Discovery": { + "PopularTab": "Popular", + "TrendingTab": "Trending", + "UpcomingTab": "Upcoming", + "SeasonalTab": "Seasonal", + "RecentlyRequestedTab": "Recently Requested", + "Movies": "Movies", + "Combined": "Combined", + "Tv": "TV", + "CardDetails": { + "Availability": "Availability", + "Studio": "Studio", + "Network": "Network", + "UnknownNetwork": "Unknown", + "RequestStatus": "Request Status", + "Director": "Director", + "InCinemas": "In Cinemas", + "FirstAired": "First Aired", + "Writer": "Writer", + "ExecProducer": "Exec Producer" + }, + "NoSearch": "Sorry, nothing matches your search!" + }, + "UserPreferences": { + "Welcome": "Welcome {{username}}!", + "OmbiLanguage": "Language", + "DarkMode": "Dark Mode", + "Updated": "Successfully Updated", + "StreamingCountry": "Streaming Country", + "StreamingCountryDescription": "This is the country code that we will display streaming information for. If you are in the US please select US and you will get US related streaming information.", + "LanguageDescription": "This is the language you would like the Ombi interface to be displayed in.", + "MobileQRCode": "Mobile QR Code", + "LegacyApp": "Launch Legacy App", + "NoQrCode": "Please contact your administrator to enable QR codes", + "UserType": "User Type:", + "ChangeDetails": "Change Details", + "NeedCurrentPassword": "You need your current password to make any changes here", + "CurrentPassword": "Current Password", + "EmailAddress": "Email Address", + "NewPassword": "New Password", + "NewPasswordConfirm": "New Password Confirm", + "Security": "Security", + "Profile": "Profile", + "UpdatedYourInformation": "Updated your information", + "Unsubscribed": "Unsubscribed!" + }, + "UserTypeLabel": { + "1": "Local User", + "2": "Plex User", + "3": "Emby User", + "4": "Emby Connect User", + "5": "Jellyfin User" + }, + "Paginator": { + "itemsPerPageLabel": "Items per page:", + "nextPageLabel": "Next page", + "previousPageLabel": "Previous page", + "firstPageLabel": "First page", + "lastPageLabel": "Last page", + "rangePageLabel1": "0 of {{length}}", + "rangePageLabel2": "{{startIndex}} – {{endIndex}} of {{length}}" + } +} diff --git a/src/Ombi/wwwroot/translations/da.json b/src/Ombi/wwwroot/translations/da.json index 46236f6d1..1598df272 100644 --- a/src/Ombi/wwwroot/translations/da.json +++ b/src/Ombi/wwwroot/translations/da.json @@ -226,7 +226,12 @@ "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" - } + }, + "Notify": "Notify", + "RemoveNotification": "Remove Notifications", + "SuccessfulNotify": "You will now be notified for title {{title}}", + "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", + "CouldntNotify": "Couldn't notify title {{title}}" }, "Issues": { "Title": "Problemer", diff --git a/src/Ombi/wwwroot/translations/de.json b/src/Ombi/wwwroot/translations/de.json index 20da24e6b..9ed748ac5 100644 --- a/src/Ombi/wwwroot/translations/de.json +++ b/src/Ombi/wwwroot/translations/de.json @@ -226,7 +226,12 @@ "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" - } + }, + "Notify": "Notify", + "RemoveNotification": "Remove Notifications", + "SuccessfulNotify": "You will now be notified for title {{title}}", + "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", + "CouldntNotify": "Couldn't notify title {{title}}" }, "Issues": { "Title": "Probleme", diff --git a/src/Ombi/wwwroot/translations/es.json b/src/Ombi/wwwroot/translations/es.json index 1942200dd..8bf684664 100644 --- a/src/Ombi/wwwroot/translations/es.json +++ b/src/Ombi/wwwroot/translations/es.json @@ -226,7 +226,12 @@ "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" - } + }, + "Notify": "Notify", + "RemoveNotification": "Remove Notifications", + "SuccessfulNotify": "You will now be notified for title {{title}}", + "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", + "CouldntNotify": "Couldn't notify title {{title}}" }, "Issues": { "Title": "Problemas", diff --git a/src/Ombi/wwwroot/translations/fr.json b/src/Ombi/wwwroot/translations/fr.json index 16aafcec3..298a87aba 100644 --- a/src/Ombi/wwwroot/translations/fr.json +++ b/src/Ombi/wwwroot/translations/fr.json @@ -226,7 +226,12 @@ "MovieRequestQuotaExceeded": "Vous avez dépassé votre quota de demandes de films !", "TvRequestQuotaExceeded": "Vous avez dépassé votre quota de demandes d'épisodes !", "AlbumRequestQuotaExceeded": "Vous avez dépassé votre quota de demandes d'albums !" - } + }, + "Notify": "Notifier", + "RemoveNotification": "Supprimer les notifications", + "SuccessfulNotify": "Vous allez maintenant être notifié pour {{title}}", + "SuccessfulUnNotify": "Vous ne serez plus notifié pour {{title}}", + "CouldntNotify": "Impossible de notifier {{title}}" }, "Issues": { "Title": "Problèmes", @@ -310,13 +315,13 @@ "Status": "Statut :", "StatusValues": { "Rumored": "Rumeur", - "Planned": "Planifié", + "Planned": "Prévu", "In Production": "En Production", "Post Production": "Post-production", "Released": "Sorti", "Running": "En cours", "Returning Series": "Série en cours", - "Ended": "Finie", + "Ended": "Terminée", "Canceled": "Annulée" }, "Seasons": "Saisons :", @@ -324,13 +329,13 @@ "Availability": "Disponibilité :", "RequestStatus": "Statut de la Demande", "Quality": "Qualité :", - "RootFolderOverride": "Remplacement du répertoire racine :", - "QualityOverride": "Remplacement de la qualité :", + "RootFolderOverride": "Répertoire racine remplacé :", + "QualityOverride": "Qualité remplacée :", "Network": "Diffuseur :", "GenresLabel": "Genres :", "Genres": "Genres", "FirstAired": "Première diffusion :", - "TheatricalRelease": "Sortie :", + "TheatricalRelease": "Sortie en salle :", "DigitalRelease": "Sortie numérique :", "Votes": "Votes :", "Runtime": "Durée :", diff --git a/src/Ombi/wwwroot/translations/hu.json b/src/Ombi/wwwroot/translations/hu.json index 0184fadf7..7797e1318 100644 --- a/src/Ombi/wwwroot/translations/hu.json +++ b/src/Ombi/wwwroot/translations/hu.json @@ -62,7 +62,7 @@ "Discover": "Felfedezés", "Search": "Keresés", "Requests": "Kérések", - "UserManagement": "Felhasználók kezelése", + "UserManagement": "Felhasználók", "Issues": "Problémák", "Vote": "Szavazás", "Donate": "Adakozás!", @@ -78,7 +78,7 @@ "ChangeTheme": "Téma váltása", "Calendar": "Naptár", "UserPreferences": "Beállítások", - "FeatureSuggestion": "Feature Suggestion", + "FeatureSuggestion": "Funkciójavaslás", "FeatureSuggestionTooltip": "Van egy jó ötleted? Oszd meg itt!", "Filter": { "Movies": "Filmek", @@ -219,14 +219,19 @@ "NoPermissionsOnBehalf": "Nincs jogosultságod más felhasználók nevében kérni!", "NoPermissions": "Nincs megfelelő jogosultságod!", "RequestDoesNotExist": "A kérés nem létezik", - "ChildRequestDoesNotExist": "Child Request does not exist", + "ChildRequestDoesNotExist": "Gyerek kérés nem létezik", "NoPermissionsRequestMovie": "Nincs jogosultságod filmet kérni", "NoPermissionsRequestTV": "Nincs jogosultságod sorozatot kérni", "NoPermissionsRequestAlbum": "Nincs jogosultságod albumot kérni", "MovieRequestQuotaExceeded": "Túllépted a megszabott film kérési kereted!", "TvRequestQuotaExceeded": "Túllépted a megszabott epizód kérési kereted!", "AlbumRequestQuotaExceeded": "Túllépted a megszabott album kérési kereted!" - } + }, + "Notify": "Értesítés", + "RemoveNotification": "Értesítések törlése", + "SuccessfulNotify": "Mostantól értesítve leszel erről: {{title}}", + "SuccessfulUnNotify": "Mostantól nem leszel értesítve erről: {{title}}", + "CouldntNotify": "Nem lehetett értesíteni erről: {{title}}" }, "Issues": { "Title": "Problémák", diff --git a/src/Ombi/wwwroot/translations/it.json b/src/Ombi/wwwroot/translations/it.json index 602db4105..d1c910b66 100644 --- a/src/Ombi/wwwroot/translations/it.json +++ b/src/Ombi/wwwroot/translations/it.json @@ -226,7 +226,12 @@ "MovieRequestQuotaExceeded": "Hai superato la tua quota di richieste di Film!", "TvRequestQuotaExceeded": "Hai superato la tua quota di richieste di Episodi!", "AlbumRequestQuotaExceeded": "Hai superato la tua quota di richieste di Album!" - } + }, + "Notify": "Notifica", + "RemoveNotification": "Rimuovi Notifiche", + "SuccessfulNotify": "Sarai notificato per il titolo {{title}}", + "SuccessfulUnNotify": "Non sarai più notificato per il titolo {{title}}", + "CouldntNotify": "Impossibile notificare il titolo {{title}}" }, "Issues": { "Title": "Problemi", @@ -273,7 +278,7 @@ "FilterHeaderRequestStatus": "Stato", "Approved": "Approvato", "PendingApproval": "In attesa di approvazione", - "WatchProviders": "Watch Providers", + "WatchProviders": "Guarda i Fornitori", "Keywords": "Parole Chiave" }, "UserManagment": { diff --git a/src/Ombi/wwwroot/translations/nl.json b/src/Ombi/wwwroot/translations/nl.json index 9227a57cb..801f48479 100644 --- a/src/Ombi/wwwroot/translations/nl.json +++ b/src/Ombi/wwwroot/translations/nl.json @@ -226,7 +226,12 @@ "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" - } + }, + "Notify": "Notify", + "RemoveNotification": "Remove Notifications", + "SuccessfulNotify": "You will now be notified for title {{title}}", + "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", + "CouldntNotify": "Couldn't notify title {{title}}" }, "Issues": { "Title": "Problemen", diff --git a/src/Ombi/wwwroot/translations/no.json b/src/Ombi/wwwroot/translations/no.json index 69d2eb3a6..41e027c37 100644 --- a/src/Ombi/wwwroot/translations/no.json +++ b/src/Ombi/wwwroot/translations/no.json @@ -226,7 +226,12 @@ "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" - } + }, + "Notify": "Notify", + "RemoveNotification": "Remove Notifications", + "SuccessfulNotify": "You will now be notified for title {{title}}", + "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", + "CouldntNotify": "Couldn't notify title {{title}}" }, "Issues": { "Title": "Mangler", diff --git a/src/Ombi/wwwroot/translations/pl.json b/src/Ombi/wwwroot/translations/pl.json index eca800305..e1a2ad62e 100644 --- a/src/Ombi/wwwroot/translations/pl.json +++ b/src/Ombi/wwwroot/translations/pl.json @@ -226,7 +226,12 @@ "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" - } + }, + "Notify": "Notify", + "RemoveNotification": "Remove Notifications", + "SuccessfulNotify": "You will now be notified for title {{title}}", + "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", + "CouldntNotify": "Couldn't notify title {{title}}" }, "Issues": { "Title": "Problemy", diff --git a/src/Ombi/wwwroot/translations/pt.json b/src/Ombi/wwwroot/translations/pt.json index b0c470c20..ea1967e78 100644 --- a/src/Ombi/wwwroot/translations/pt.json +++ b/src/Ombi/wwwroot/translations/pt.json @@ -1,203 +1,203 @@ { "Login": { - "SignInButton": "Sign in", - "UsernamePlaceholder": "Username", - "PasswordPlaceholder": "Password", - "RememberMe": "Remember Me", - "SignInWith": "Sign in with {{appName}}", - "SignInWithPlex": "Sign in with Plex", - "ForgottenPassword": "Forgot your password?", + "SignInButton": "Iniciar sessão", + "UsernamePlaceholder": "Nome de usuário", + "PasswordPlaceholder": "Senha", + "RememberMe": "Lembrar-me", + "SignInWith": "Entre com {{appName}}", + "SignInWithPlex": "Iniciar sessão com Plex", + "ForgottenPassword": "Esqueceu sua senha?", "Errors": { - "IncorrectCredentials": "Incorrect username or password" + "IncorrectCredentials": "Nome de usuário ou senha incorretos" } }, "Common": { - "ContinueButton": "Continue", - "Available": "Available", - "Approved": "Approved", - "Pending": "Pending", - "PartiallyAvailable": "Partially Available", - "Monitored": "Monitored", - "NotAvailable": "Not Available", - "ProcessingRequest": "Processing Request", - "PendingApproval": "Pending Approval", - "RequestDenied": "Request Denied", - "NotRequested": "Not Requested", - "Requested": "Requested", - "Search": "Search", - "Request": "Request", - "Denied": "Denied", - "Approve": "Approve", - "PartlyAvailable": "Partly Available", - "ViewDetails": "View Details", + "ContinueButton": "Continuar", + "Available": "Disponível", + "Approved": "Aprovado", + "Pending": "Pendente", + "PartiallyAvailable": "Parcialmente Disponível", + "Monitored": "Monitorado", + "NotAvailable": "Não Disponível", + "ProcessingRequest": "Processando Solicitação", + "PendingApproval": "Aprovação Pendente", + "RequestDenied": "Solicitação Negada", + "NotRequested": "Não Solicitado", + "Requested": "Solicitado", + "Search": "Buscar", + "Request": "Solicitar", + "Denied": "Negado", + "Approve": "Aprovar", + "PartlyAvailable": "Parcialmente Disponível", + "ViewDetails": "Ver detalhes", "Errors": { - "Validation": "Please check your entered values" + "Validation": "Por favor, verifique os dados inseridos" }, - "Cancel": "Cancel", - "Submit": "Submit", - "Update": "Update", - "tvShow": "TV Show", - "movie": "Movie", - "album": "Album" + "Cancel": "Cancelar", + "Submit": "Submeter", + "Update": "Atualizar", + "tvShow": "Series", + "movie": "Filmes", + "album": "Álbum" }, "PasswordReset": { - "EmailAddressPlaceholder": "Email Address", - "ResetPasswordButton": "Reset Password" + "EmailAddressPlaceholder": "Endereço de e-mail", + "ResetPasswordButton": "Redefinir Senha" }, "LandingPage": { - "OnlineHeading": "Currently Online", - "OnlineParagraph": "The media server is currently online", - "PartiallyOnlineHeading": "Partially Online", - "PartiallyOnlineParagraph": "The media server is partially online.", - "MultipleServersUnavailable": "There are {{serversUnavailable}} servers offline out of {{totalServers}}.", - "SingleServerUnavailable": "There is {{serversUnavailable}} server offline out of {{totalServers}}.", - "OfflineHeading": "Currently Offline", - "OfflineParagraph": "The media server is currently offline.", - "CheckPageForUpdates": "Check this page for continuous site updates." + "OnlineHeading": "Online no momento", + "OnlineParagraph": "O servidor de mídia está atualmente online", + "PartiallyOnlineHeading": "Parcialmente Online", + "PartiallyOnlineParagraph": "O servidor de mídia está parcialmente online.", + "MultipleServersUnavailable": "Existem {{serversUnavailable}} servidores offline de um total de {{totalServers}}.", + "SingleServerUnavailable": "Existe {{serversUnavailable}} servidor offline de um total de {{totalServers}}.", + "OfflineHeading": "Offline Agora", + "OfflineParagraph": "O servidor de mídia está atualmente offline.", + "CheckPageForUpdates": "Verifique esta página para acompanhar as atualizações do site." }, "ErrorPages": { - "NotFound": "Page not found" + "NotFound": "Pagina não encontrada" }, "NavigationBar": { - "Discover": "Discover", - "Search": "Search", - "Requests": "Requests", - "UserManagement": "Users", - "Issues": "Issues", - "Vote": "Vote", - "Donate": "Donate!", - "DonateLibraryMaintainer": "Donate to Library Maintainer", - "DonateTooltip": "This is how I convince my wife to let me spend my spare time developing Ombi 😁", - "UpdateAvailableTooltip": "Update Available!", - "Settings": "Settings", - "Welcome": "Welcome {{username}}", - "UpdateDetails": "Update Details", - "Logout": "Logout", - "OpenMobileApp": "Open Mobile App", - "RecentlyAdded": "Recently Added", - "ChangeTheme": "Change Theme", - "Calendar": "Calendar", - "UserPreferences": "Preferences", - "FeatureSuggestion": "Features", - "FeatureSuggestionTooltip": "Have a great new idea? Suggest it here!", + "Discover": "Explorar", + "Search": "Pesquisar", + "Requests": "Solicitações", + "UserManagement": "User Management", + "Issues": "Problemas", + "Vote": "Votar", + "Donate": "Doações!", + "DonateLibraryMaintainer": "Doar para o Dono da Biblioteca", + "DonateTooltip": "É assim que convenço minha esposa a me deixar passar o meu tempo livre desenvolvendo o Ombi 😁", + "UpdateAvailableTooltip": "Atualização Disponível!", + "Settings": "Configurações", + "Welcome": "Bem-vindo(a), {{username}}", + "UpdateDetails": "Detalhes da Atualização", + "Logout": "Desconectar", + "OpenMobileApp": "Abrir Aplicativo do Celular", + "RecentlyAdded": "Recentemente Adicionado", + "ChangeTheme": "Trocar Tema", + "Calendar": "Calendário", + "UserPreferences": "Preferências", + "FeatureSuggestion": "Feature Suggestion", + "FeatureSuggestionTooltip": "Teve uma ótima idéia? Sugira aqui!", "Filter": { - "Movies": "Movies", - "TvShows": "TV Shows", - "Music": "Music", - "People": "People" + "Movies": "Filmes", + "TvShows": "Séries", + "Music": "Músicas", + "People": "Pessoas" }, - "MorningWelcome": "Good morning!", - "AfternoonWelcome": "Good afternoon!", - "EveningWelcome": "Good evening!" + "MorningWelcome": "Bom dia!", + "AfternoonWelcome": "Boa tarde!", + "EveningWelcome": "Boa noite!" }, "Search": { - "Title": "Search", - "Paragraph": "Want to watch something that is not currently available? No problem, just search for it below and request it!", - "MoviesTab": "Movies", - "TvTab": "TV Shows", - "MusicTab": "Music", - "AdvancedSearch": "You can fill in any of the below to discover new media. All of the results are sorted by popularity", - "AdvancedSearchHeader": "Advanced Search", - "Suggestions": "Suggestions", - "NoResults": "Sorry, we didn't find any results!", - "DigitalDate": "Digital Release: {{date}}", - "TheatricalRelease": "Theatrical Release: {{date}}", - "ViewOnPlex": "Play On Plex", - "ViewOnEmby": "Play On Emby", - "ViewOnJellyfin": "Play On Jellyfin", - "RequestAdded": "Request for {{title}} has been added successfully", - "Similar": "Similar", - "Refine": "Refine", - "SearchBarPlaceholder": "Type Here to Search", + "Title": "Pesquisar", + "Paragraph": "Quer assistir a algo que não está disponível? Sem problemas, basta pesquisar abaixo e solicitar!", + "MoviesTab": "Filmes", + "TvTab": "Séries", + "MusicTab": "Músicas", + "AdvancedSearch": "Você pode preencher qualquer um dos abaixo para descobrir novas mídias. Todos os resultados são classificados por popularidade", + "AdvancedSearchHeader": "Pesquisa avançada", + "Suggestions": "Sugestões", + "NoResults": "Desculpe, não encontramos nenhum resultado!", + "DigitalDate": "Lançamento Digital: {{date}}", + "TheatricalRelease": "Lançamento nos Cinemas: {{date}}", + "ViewOnPlex": "View On Plex", + "ViewOnEmby": "View On Emby", + "ViewOnJellyfin": "Assistir no Jellyfin", + "RequestAdded": "O pedido de {{title}} foi adicionado com sucesso", + "Similar": "Semelhantes", + "Refine": "Corrigir", + "SearchBarPlaceholder": "Digite Aqui para Pesquisar", "Movies": { - "PopularMovies": "Popular Movies", - "UpcomingMovies": "Upcoming Movies", - "TopRatedMovies": "Top Rated Movies", - "NowPlayingMovies": "Now Playing Movies", - "HomePage": "Home Page", + "PopularMovies": "Filmes Populares", + "UpcomingMovies": "Filmes Em Breve", + "TopRatedMovies": "Filmes Mais Votados", + "NowPlayingMovies": "Filmes em Cartaz", + "HomePage": "Página Inicial", "Trailer": "Trailer" }, "TvShows": { "Popular": "Popular", - "Trending": "Trending", - "MostWatched": "Most Watched", - "MostAnticipated": "Most Anticipated", - "Results": "Results", - "AirDate": "Air Date:", - "AllSeasons": "All Seasons", - "FirstSeason": "First Season", - "LatestSeason": "Latest Season", - "Select": "Select ...", - "SubmitRequest": "Submit Request", - "Season": "Season {{seasonNumber}}", - "SelectAllInSeason": "Select All in Season {{seasonNumber}}" + "Trending": "Tendências", + "MostWatched": "Mais Assistidos", + "MostAnticipated": "Mais Aguardados", + "Results": "Resultados", + "AirDate": "Data de Exibição:", + "AllSeasons": "Todas as Temporadas", + "FirstSeason": "Primeira temporada", + "LatestSeason": "Última Temporada", + "Select": "Selecionar...", + "SubmitRequest": "Enviar solicitação", + "Season": "Temporada: {{seasonNumber}}", + "SelectAllInSeason": "Selecione Tudo na Temporada {{seasonNumber}}" }, - "AdvancedSearchInstructions": "Please choose what type of media you are searching for:", - "YearOfRelease": "Year of Release", - "SearchGenre": "Search Genre", - "SearchKeyword": "Search Keyword", - "SearchProvider": "Search Provider", - "KeywordSearchingDisclaimer": "Please note that Keyword Searching is very hit and miss due to the inconsistent data in TheMovieDb" + "AdvancedSearchInstructions": "Por favor, escolha o tipo de mídia que você está procurando:", + "YearOfRelease": "Ano de lançamento", + "SearchGenre": "Pesquisa por gênero", + "SearchKeyword": "Pesquisar palavras-chave", + "SearchProvider": "Provedores de pesquisa", + "KeywordSearchingDisclaimer": "Por favor, note que a busca por palavra-chave é muito acertada e perdida devido aos dados inconsistentes no TheMovieDb" }, "Requests": { - "Title": "Requests", - "Paragraph": "Below you can see yours and all other requests, as well as their download and approval status.", - "MoviesTab": "Movies", - "ArtistName": "Artist", - "AlbumName": "Album Name", - "TvTab": "TV Shows", - "MusicTab": "Music", - "RequestedBy": "Requested By", + "Title": "Solicitações", + "Paragraph": "Abaixo, você pode ver o seu e todos os outros pedidos, bem como o seu download e status de aprovação.", + "MoviesTab": "Filmes", + "ArtistName": "Artistas", + "AlbumName": "Nome do álbum", + "TvTab": "Séries", + "MusicTab": "Músicas", + "RequestedBy": "Solicitado por", "Status": "Status", - "RequestStatus": "Request status", - "Denied": " Denied:", - "TheatricalRelease": "Theatrical Release: {{date}}", - "ReleaseDate": "Released: {{date}}", - "TheatricalReleaseSort": "Theatrical Release", - "DigitalRelease": "Digital Release: {{date}}", - "RequestDate": "Request Date", - "QualityOverride": "Quality Override:", - "RootFolderOverride": "Root Folder Override:", - "ChangeRootFolder": "Root Folder", - "ChangeQualityProfile": "Quality Profile", - "MarkUnavailable": "Mark Unavailable", - "MarkAvailable": "Mark Available", - "Remove": "Remove", - "Deny": "Deny", - "DenyReason": "Deny Reason", - "DeniedReason": "Denied Reason", - "Season": "Season", - "GridTitle": "Title", - "AirDate": "Air Date", + "RequestStatus": "Status da solicitação", + "Denied": " Negados:", + "TheatricalRelease": "Lançamento nos Cinemas: {{date}}", + "ReleaseDate": "Lançado: {{date}}", + "TheatricalReleaseSort": "Lançamento nos Cinemas", + "DigitalRelease": "Lançamento Digital: {{date}}", + "RequestDate": "Data da Solicitação", + "QualityOverride": "Substituição de Qualidade:", + "RootFolderOverride": "Substituição da Pasta Raiz:", + "ChangeRootFolder": "Pasta Raiz", + "ChangeQualityProfile": "Perfil de Qualidade", + "MarkUnavailable": "Marcar como Indisponível", + "MarkAvailable": "Marcar como Disponível", + "Remove": "Remover", + "Deny": "Negar", + "DenyReason": "Razão da rejeição", + "DeniedReason": "Razão da rejeição", + "Season": "Temporada", + "GridTitle": "Título", + "AirDate": "AirDate", "GridStatus": "Status", - "ReportIssue": "Report Issue", - "Filter": "Filter", - "Sort": "Sort", - "SeasonNumberHeading": "Season: {seasonNumber}", - "SortTitleAsc": "Title ▲", - "SortTitleDesc": "Title ▼", - "SortRequestDateAsc": "Request Date ▲", - "SortRequestDateDesc": "Request Date ▼", + "ReportIssue": "Relatar Problema", + "Filter": "Filtro", + "Sort": "Ordenar por", + "SeasonNumberHeading": "Temporada: {seasonNumber}", + "SortTitleAsc": "Título ▲", + "SortTitleDesc": "Título ▼", + "SortRequestDateAsc": "Data da Solicitação ▲", + "SortRequestDateDesc": "Data da Solicitação ▼", "SortStatusAsc": "Status ▲", "SortStatusDesc": "Status ▼", "Remaining": { - "Quota": "{{remaining}}/{{total}} requests remaining", - "NextDays": "Another request will be added in {{time}} days", - "NextHours": "Another request will be added in {{time}} hours", - "NextMinutes": "Another request will be added in {{time}} minutes", - "NextMinute": "Another request will be added in {{time}} minute" + "Quota": "{{remaining}}/{{total}} solicitações restantes", + "NextDays": "Outra solicitação será adicionada em {{time}} dias", + "NextHours": "Outra solicitação será adicionada em {{time}} horas", + "NextMinutes": "Outra solicitação será adicionada em {{time}} minutos", + "NextMinute": "Outra solicitação será adicionada em {{time}} minuto" }, - "AllRequests": "All Requests", - "PendingRequests": "Pending Requests", - "ProcessingRequests": "Processing Requests", - "AvailableRequests": "Available Requests", - "DeniedRequests": "Denied Requests", - "RequestsToDisplay": "Requests to display", - "RequestsTitle": "Title", - "Details": "Details", - "Options": "Options", + "AllRequests": "Todas solicitações", + "PendingRequests": "Solicitações pendentes", + "ProcessingRequests": "Solicitações em andamento", + "AvailableRequests": "Solicitação Disponíveis", + "DeniedRequests": "Solicitações Negadas", + "RequestsToDisplay": "Itens por página", + "RequestsTitle": "Título", + "Details": "Detalhes", + "Options": "Opções", "RequestPanel": { - "Delete": "Delete Request", + "Delete": "Apagar Solicitação", "Approve": "Approve Request", "ChangeAvailability": "Mark Available", "Deleted": "Successfully deleted selected items", @@ -226,28 +226,33 @@ "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" - } + }, + "Notify": "Notify", + "RemoveNotification": "Remove Notifications", + "SuccessfulNotify": "You will now be notified for title {{title}}", + "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", + "CouldntNotify": "Couldn't notify title {{title}}" }, "Issues": { - "Title": "Issues", + "Title": "Problemas", "IssuesForTitle": "Issues for {{title}}", - "PendingTitle": "Pending Issues", - "InProgressTitle": "In Progress Issues", - "ResolvedTitle": "Resolved Issues", - "ColumnTitle": "Title", + "PendingTitle": "Problemas pendentes", + "InProgressTitle": "Problemas em resolução", + "ResolvedTitle": "Problemas Resolvidos", + "ColumnTitle": "Título", "Count": "Count", - "Category": "Category", + "Category": "Categoria", "Status": "Status", - "Details": "Details", - "Description": "Description", - "NoComments": "No Comments!", - "MarkInProgress": "Mark In Progress", - "MarkResolved": "Mark Resolved", - "SendMessageButton": "Send", - "Subject": "Subject", - "Comments": "Comments", - "WriteMessagePlaceholder": "Write your message here...", - "ReportedBy": "Reported By", + "Details": "Detalhes", + "Description": "Descrição", + "NoComments": "Sem Comentários!", + "MarkInProgress": "Marcar como em andamento", + "MarkResolved": "Marcar como resolvido", + "SendMessageButton": "Enviar", + "Subject": "Assunto", + "Comments": "Comentários", + "WriteMessagePlaceholder": "Escreva sua mensagem aqui...", + "ReportedBy": "Reportado por", "IssueDialog": { "Title": "Report an issue", "DescriptionPlaceholder": "Please describe the issue", @@ -268,35 +273,35 @@ "UserOnDate": "{{user}} on {{date}}" }, "Filter": { - "ClearFilter": "Clear Filter", - "FilterHeaderAvailability": "Availability", + "ClearFilter": "Limpar Filtro", + "FilterHeaderAvailability": "Disponibilidade", "FilterHeaderRequestStatus": "Status", - "Approved": "Approved", - "PendingApproval": "Pending Approval", + "Approved": "Aprovado", + "PendingApproval": "Aprovação Pendente", "WatchProviders": "Watch Providers", "Keywords": "Keywords" }, "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} remaining", - "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", - "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", - "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}", - "MusicDue": "Music: {{date}}" + "TvRemaining": "Séries: {{remaining}}/{{total}} restantes", + "MovieRemaining": "Filmes: {{remaining}}/{{total}} restantes", + "MusicRemaining": "Músicas: {{remaining}}/{{total}} restantes", + "TvDue": "Série: {{date}}", + "MovieDue": "Filme: {{date}}", + "MusicDue": "Música: {{date}}" }, "Votes": { - "CompletedVotesTab": "Voted", - "VotesTab": "Votes Needed" + "CompletedVotesTab": "Votado", + "VotesTab": "Votos necessários" }, "MediaDetails": { "Denied": "Denied", "Trailers": "Trailers", "RecommendationsTitle": "Recommendations", "SimilarTitle": "Similar", - "VideosTitle": "Videos", - "AlbumsTitle": "Albums", - "RequestAllAlbums": "Request All Albums", - "ClearSelection": "Clear Selection", + "VideosTitle": "Vídeos", + "AlbumsTitle": "Álbuns", + "RequestAllAlbums": "Solicitar Todos Álbuns", + "ClearSelection": "Limpar Seleção", "RequestSelectedAlbums": "Request Selected Albums", "ViewCollection": "View Collection", "NotEnoughInfo": "Unfortunately there is not enough information about this show yet!", diff --git a/src/Ombi/wwwroot/translations/ru.json b/src/Ombi/wwwroot/translations/ru.json index 98824107d..0f57f9c31 100644 --- a/src/Ombi/wwwroot/translations/ru.json +++ b/src/Ombi/wwwroot/translations/ru.json @@ -226,7 +226,12 @@ "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" - } + }, + "Notify": "Notify", + "RemoveNotification": "Remove Notifications", + "SuccessfulNotify": "You will now be notified for title {{title}}", + "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", + "CouldntNotify": "Couldn't notify title {{title}}" }, "Issues": { "Title": "Проблемы", diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json index 4c46d760c..1e0ae25cf 100644 --- a/src/Ombi/wwwroot/translations/sk.json +++ b/src/Ombi/wwwroot/translations/sk.json @@ -226,7 +226,12 @@ "MovieRequestQuotaExceeded": "Prekročili ste limit požiadaviek na filmy!", "TvRequestQuotaExceeded": "Prekročili ste limit požiadaviek na epizódy!", "AlbumRequestQuotaExceeded": "Prekročili ste limit požiadaviek na albumy!" - } + }, + "Notify": "Notify", + "RemoveNotification": "Remove Notifications", + "SuccessfulNotify": "You will now be notified for title {{title}}", + "SuccessfulUnNotify": "You will no longer be notified for title {{title}}", + "CouldntNotify": "Couldn't notify title {{title}}" }, "Issues": { "Title": "Problémy", diff --git a/src/Ombi/wwwroot/translations/sv.json b/src/Ombi/wwwroot/translations/sv.json index 1eea33f56..8532930be 100644 --- a/src/Ombi/wwwroot/translations/sv.json +++ b/src/Ombi/wwwroot/translations/sv.json @@ -226,7 +226,12 @@ "MovieRequestQuotaExceeded": "You have exceeded your Movie request quota!", "TvRequestQuotaExceeded": "You have exceeded your Episode request quota!", "AlbumRequestQuotaExceeded": "You have exceeded your Album request quota!" - } + }, + "Notify": "Avisering", + "RemoveNotification": "Ta bort avisering", + "SuccessfulNotify": "Du kommer nu att aviseras för titel {{title}}", + "SuccessfulUnNotify": "Du kommer inte längre att aviseras för titel {{title}}", + "CouldntNotify": "Kunde inte avisera för {{title}}" }, "Issues": { "Title": "Problem", diff --git a/src/Ombi/wwwroot/translations/zh.json b/src/Ombi/wwwroot/translations/zh.json index 6ba2f59e2..453ef7418 100644 --- a/src/Ombi/wwwroot/translations/zh.json +++ b/src/Ombi/wwwroot/translations/zh.json @@ -226,7 +226,12 @@ "MovieRequestQuotaExceeded": "您的电影请求已超出配额!", "TvRequestQuotaExceeded": "您的剧集请求已超出配额!", "AlbumRequestQuotaExceeded": "您的专辑请求已超出配额!" - } + }, + "Notify": "通知", + "RemoveNotification": "删除通知", + "SuccessfulNotify": "您将收到标题为 {{title}} 的通知", + "SuccessfulUnNotify": "您将不再收到标题为 {{title}} 的通知", + "CouldntNotify": "无法通知标题 {{title}}" }, "Issues": { "Title": "问题", From 35806ea2d2c866d628cf08577026a02ab04e49d9 Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Fri, 14 Jan 2022 10:13:20 +0100 Subject: [PATCH 08/20] =?UTF-8?q?fix(discover):=20=F0=9F=8C=90=20Localize?= =?UTF-8?q?=20episodes=20names=20in=20TV=20details=20(#4467)=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs index 2fcff7439..07f8ce981 100644 --- a/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs @@ -89,7 +89,7 @@ namespace Ombi.Core.Engine.V2 foreach (var tvSeason in show.seasons.Where(x => x.season_number != 0)) // skip the first season { - var seasonEpisodes = (await _movieApi.GetSeasonEpisodes(show.id, tvSeason.season_number, token)); + var seasonEpisodes = (await _movieApi.GetSeasonEpisodes(show.id, tvSeason.season_number, token, langCode)); MapSeasons(mapped.SeasonRequests, tvSeason, seasonEpisodes); } From ad677fa02eb75633014e9c9791c21ed2d6a23229 Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Fri, 14 Jan 2022 10:18:43 +0100 Subject: [PATCH 09/20] fix(emby/jellyfin): :bug: A more reliable Emby and Jellyfin sync [skip ci] * Fix 100th Emby episode not being synced Emby API is zero-based offset * Fix 100th Emby TV show and movie not being synced * Fix Jellyfin API offset error --- src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs | 4 ++-- src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs | 2 +- src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs | 4 ++-- src/Ombi.Schedule/Jobs/Jellyfin/JellyfinEpisodeSync.cs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs index 5f9c294a7..154ae784f 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs @@ -143,7 +143,7 @@ namespace Ombi.Schedule.Jobs.Emby tv = await Api.GetAllShows(server.ApiKey, parentId, 0, AmountToTake, server.AdministratorId, server.FullUri); } var totalTv = tv.TotalRecordCount; - var processed = 1; + var processed = 0; while (processed < totalTv) { foreach (var tvShow in tv.Items) @@ -207,7 +207,7 @@ namespace Ombi.Schedule.Jobs.Emby movies = await Api.GetAllMovies(server.ApiKey, parentId, 0, AmountToTake, server.AdministratorId, server.FullUri); } var totalCount = movies.TotalRecordCount; - var processed = 1; + var processed = 0; var mediaToAdd = new HashSet(); while (processed < totalCount) { diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs index 5b2bbd892..c1ca48ef7 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyEpisodeSync.cs @@ -122,7 +122,7 @@ namespace Ombi.Schedule.Jobs.Emby allEpisodes = await Api.GetAllEpisodes(server.ApiKey, parentIdFilter, 0, AmountToTake, server.AdministratorId, server.FullUri); } var total = allEpisodes.TotalRecordCount; - var processed = 1; + var processed = 0; var epToAdd = new HashSet(); while (processed < total) { diff --git a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs index 2a950fcf4..e8de12bd2 100644 --- a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinContentSync.cs @@ -118,7 +118,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin var mediaToAdd = new HashSet(); var tv = await Api.GetAllShows(server.ApiKey, parentId, 0, 200, server.AdministratorId, server.FullUri); var totalTv = tv.TotalRecordCount; - var processed = 1; + var processed = 0; while (processed < totalTv) { foreach (var tvShow in tv.Items) @@ -177,7 +177,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin { var movies = await Api.GetAllMovies(server.ApiKey, parentId, 0, 200, server.AdministratorId, server.FullUri); var totalCount = movies.TotalRecordCount; - var processed = 1; + var processed = 0; var mediaToAdd = new HashSet(); while (processed < totalCount) { diff --git a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinEpisodeSync.cs index 60f500d19..27e50c9b7 100644 --- a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinEpisodeSync.cs @@ -98,7 +98,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin { var allEpisodes = await Api.GetAllEpisodes(server.ApiKey, parentIdFilter, 0, 200, server.AdministratorId, server.FullUri); var total = allEpisodes.TotalRecordCount; - var processed = 1; + var processed = 0; var epToAdd = new HashSet(); while (processed < total) { From 0ece2fd6e0eb01e0b7d4d2a01e1a276c7a9c5a51 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Fri, 14 Jan 2022 10:09:50 +0000 Subject: [PATCH 10/20] fix(email-notifications): :bug: Fixed the issue where legacy requests were showing broken poster images #4452 --- .../NotificationMessageCurlys.cs | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/Ombi.Notifications/NotificationMessageCurlys.cs b/src/Ombi.Notifications/NotificationMessageCurlys.cs index 8023ae464..924864c62 100644 --- a/src/Ombi.Notifications/NotificationMessageCurlys.cs +++ b/src/Ombi.Notifications/NotificationMessageCurlys.cs @@ -43,7 +43,17 @@ namespace Ombi.Notifications var img = req?.PosterPath ?? string.Empty; if (img.HasValue()) { - PosterImage = $"https://image.tmdb.org/t/p/w300/{req?.PosterPath?.TrimStart('/') ?? string.Empty}"; + if (img.StartsWith("http")) + { + // This means it's a legacy request from when we used TvMaze as a provider. + // The poster url is the fully qualified address, so just use it + PosterImage = img; + } + else + { + PosterImage = + $"https://image.tmdb.org/t/p/w300/{img?.TrimStart('/') ?? string.Empty}"; + } } CalculateRequestStatus(req); } @@ -61,8 +71,17 @@ namespace Ombi.Notifications var img = req?.ParentRequest?.PosterPath ?? string.Empty; if (img.HasValue()) { - PosterImage = - $"https://image.tmdb.org/t/p/w300/{req?.ParentRequest?.PosterPath?.TrimStart('/') ?? string.Empty}"; + if (img.StartsWith("http")) + { + // This means it's a legacy request from when we used TvMaze as a provider. + // The poster url is the fully qualified address, so just use it + PosterImage = img; + } + else + { + PosterImage = + $"https://image.tmdb.org/t/p/w300/{img?.TrimStart('/') ?? string.Empty}"; + } } // Generate episode list. From ba96676fc682c2230e9d9dede5f852c70f659b17 Mon Sep 17 00:00:00 2001 From: contrib-readme-bot Date: Fri, 14 Jan 2022 10:10:06 +0000 Subject: [PATCH 11/20] chore: :busts_in_silhouette: Updated Contributors [skip ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7ed4e2dcc..6b785e94f 100644 --- a/README.md +++ b/README.md @@ -734,7 +734,7 @@ Here are some of the features Ombi has: maartenheebink
- maartenheebink + Maartenheebink
From c044bd3e653737509b88acb65c343e7a57c02693 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Fri, 14 Jan 2022 10:12:51 +0000 Subject: [PATCH 12/20] chore(release): :rocket: v4.9.1 --- CHANGELOG.md | 22 +++++++++++----------- version.json | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3ffebb10..ea6e3359f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +## [4.9.1](https://github.com/Ombi-app/Ombi/compare/v4.9.0...v4.9.1) (2022-01-14) + + +### Bug Fixes + +* **discover:** 🌐 Localize episodes names in TV details ([#4467](https://github.com/Ombi-app/Ombi/issues/4467)) [skip ci] ([35806ea](https://github.com/Ombi-app/Ombi/commit/35806ea2d2c866d628cf08577026a02ab04e49d9)) +* **email-notifications:** :bug: Fixed the issue where legacy requests were showing broken poster images [#4452](https://github.com/Ombi-app/Ombi/issues/4452) ([0ece2fd](https://github.com/Ombi-app/Ombi/commit/0ece2fd6e0eb01e0b7d4d2a01e1a276c7a9c5a51)) +* **emby/jellyfin:** :bug: A more reliable Emby and Jellyfin sync [skip ci] ([ad677fa](https://github.com/Ombi-app/Ombi/commit/ad677fa02eb75633014e9c9791c21ed2d6a23229)) + + + # [4.9.0](https://github.com/Ombi-app/Ombi/compare/v4.8.1...v4.9.0) (2022-01-05) @@ -170,14 +181,3 @@ -## [4.6.1](https://github.com/Ombi-app/Ombi/compare/v4.6.0...v4.6.1) (2021-11-10) - - -### Bug Fixes - -* :bug: Fixed the MySQL issue after .net 6 upgrade [#4393](https://github.com/Ombi-app/Ombi/issues/4393) ([fea7ff0](https://github.com/Ombi-app/Ombi/commit/fea7ff05139e9ff50c8097fa5389b4ef9ad21a15)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([c6acb45](https://github.com/Ombi-app/Ombi/commit/c6acb45f8d3f371c0b4024c4272849d0d0cc867f)) -* **translations:** 🌐 New translations from Crowdin [skip ci] ([18c220a](https://github.com/Ombi-app/Ombi/commit/18c220a0cd0d19e45a07d0c319da2b9512778a8a)) - - - diff --git a/version.json b/version.json index a44547047..5d721d005 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.9.0" + "version": "4.9.1" } \ No newline at end of file From 5c691dc98437a4cd24560ff625414fe05dd22f89 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Fri, 14 Jan 2022 10:21:54 +0000 Subject: [PATCH 13/20] fix(sonarr): :bug: Fixed an issue where we could attempt to add a series to sonarr before sonarr has got all the metadata #4459 --- src/Ombi.Core/Senders/TvSender.cs | 32 +++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/Ombi.Core/Senders/TvSender.cs b/src/Ombi.Core/Senders/TvSender.cs index 2f42a12c0..bb2a5d628 100644 --- a/src/Ombi.Core/Senders/TvSender.cs +++ b/src/Ombi.Core/Senders/TvSender.cs @@ -309,6 +309,20 @@ namespace Ombi.Core.Senders private async Task SendToSonarr(ChildRequests model, SonarrSeries result, SonarrSettings s) { + // Check to ensure we have the all the seasons, ensure the Sonarr metadata has grabbed all the data + foreach (var season in model.SeasonRequests) + { + var attempt = 0; + var existingSeason = result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber); + while (existingSeason == null && attempt < 5) + { + attempt++; + Logger.LogInformation("There was no season numer {0} in Sonarr for title {1}. Will try again as the metadata did not get created", season.SeasonNumber, model.ParentRequest.Title); + result = await SonarrApi.GetSeriesById(result.id, s.ApiKey, s.FullUri); + await Task.Delay(500); + } + } + var episodesToUpdate = new List(); // Ok, now let's sort out the episodes. @@ -327,10 +341,11 @@ namespace Ombi.Core.Senders await Task.Delay(500); } + var seriesChanges = false; - foreach (var req in model.SeasonRequests) + foreach (var season in model.SeasonRequests) { - foreach (var ep in req.Episodes) + foreach (var ep in season.Episodes) { var sonarrEp = sonarrEpList.FirstOrDefault(x => x.episodeNumber == ep.EpisodeNumber && x.seasonNumber == req.SeasonNumber); @@ -340,11 +355,6 @@ namespace Ombi.Core.Senders episodesToUpdate.Add(sonarrEp); } } - } - var seriesChanges = false; - - foreach (var season in model.SeasonRequests) - { var sonarrEpisodeList = sonarrEpList.Where(x => x.seasonNumber == season.SeasonNumber).ToList(); var sonarrEpCount = sonarrEpisodeList.Count; var ourRequestCount = season.Episodes.Count; @@ -358,13 +368,7 @@ namespace Ombi.Core.Senders //var distinctEpisodes = ourEpisodes.Distinct().ToList(); //var missingEpisodes = Enumerable.Range(distinctEpisodes.Min(), distinctEpisodes.Count).Except(distinctEpisodes); - var existingSeason = - result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber); - if (existingSeason == null) - { - Logger.LogError("There was no season numer {0} in Sonarr for title {1}", season.SeasonNumber, model.ParentRequest.Title); - continue; - } + if (sonarrEpCount == ourRequestCount /*|| !missingEpisodes.Any()*/) From 33b8d1111a1c6663d8c0bbd912be4660da7d013f Mon Sep 17 00:00:00 2001 From: tidusjar Date: Fri, 14 Jan 2022 10:49:52 +0000 Subject: [PATCH 14/20] fix(wizard): :bug: Fixed the issue where the Application Url wasn't validated in the wizard #4417 --- src/Ombi.Core/Senders/TvSender.cs | 10 ++-- .../app/wizard/welcome/welcome.component.ts | 54 +++++++++++++------ src/Ombi/Controllers/V1/SettingsController.cs | 1 + 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/src/Ombi.Core/Senders/TvSender.cs b/src/Ombi.Core/Senders/TvSender.cs index bb2a5d628..9f60d2ba0 100644 --- a/src/Ombi.Core/Senders/TvSender.cs +++ b/src/Ombi.Core/Senders/TvSender.cs @@ -310,15 +310,17 @@ namespace Ombi.Core.Senders private async Task SendToSonarr(ChildRequests model, SonarrSeries result, SonarrSettings s) { // Check to ensure we have the all the seasons, ensure the Sonarr metadata has grabbed all the data + Season existingSeason = null; foreach (var season in model.SeasonRequests) { var attempt = 0; - var existingSeason = result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber); + existingSeason = result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber); while (existingSeason == null && attempt < 5) { attempt++; Logger.LogInformation("There was no season numer {0} in Sonarr for title {1}. Will try again as the metadata did not get created", season.SeasonNumber, model.ParentRequest.Title); result = await SonarrApi.GetSeriesById(result.id, s.ApiKey, s.FullUri); + existingSeason = result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber); await Task.Delay(500); } } @@ -348,7 +350,7 @@ namespace Ombi.Core.Senders foreach (var ep in season.Episodes) { var sonarrEp = sonarrEpList.FirstOrDefault(x => - x.episodeNumber == ep.EpisodeNumber && x.seasonNumber == req.SeasonNumber); + x.episodeNumber == ep.EpisodeNumber && x.seasonNumber == season.SeasonNumber); if (sonarrEp != null && !sonarrEp.monitored) { sonarrEp.monitored = true; @@ -366,9 +368,7 @@ namespace Ombi.Core.Senders //// NOTE, not sure if needed since ombi ui displays future episodes anyway... //ourEpisodes.AddRange(unairedEpisodes); //var distinctEpisodes = ourEpisodes.Distinct().ToList(); - //var missingEpisodes = Enumerable.Range(distinctEpisodes.Min(), distinctEpisodes.Count).Except(distinctEpisodes); - - + //var missingEpisodes = Enumerable.Range(distinctEpisodes.Min(), distinctEpisodes.Count).Except(distinctEpisodes); if (sonarrEpCount == ourRequestCount /*|| !missingEpisodes.Any()*/) diff --git a/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.ts b/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.ts index 849977b55..ef29266d1 100644 --- a/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.ts +++ b/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.ts @@ -1,11 +1,11 @@ import { AfterViewInit, Component, OnInit, ViewChild } from "@angular/core"; -import { Router } from "@angular/router"; +import { IdentityService, NotificationService, SettingsService } from "../../services"; + import { ICreateWizardUser } from "../../interfaces"; -import { IdentityService, NotificationService } from "../../services"; import { IOmbiConfigModel } from "../models/OmbiConfigModel"; -import { WizardService } from "../services/wizard.service"; import { MatHorizontalStepper } from'@angular/material/stepper'; -import { StepperSelectionEvent } from "@angular/cdk/stepper"; +import { Router } from "@angular/router"; +import { WizardService } from "../services/wizard.service"; @Component({ templateUrl: "./welcome.component.html", @@ -18,7 +18,8 @@ export class WelcomeComponent implements OnInit { public config: IOmbiConfigModel; constructor(private router: Router, private identityService: IdentityService, - private notificationService: NotificationService, private WizardService: WizardService) { } + private notificationService: NotificationService, private WizardService: WizardService, + private settingsService: SettingsService) { } public ngOnInit(): void { this.localUser = { @@ -34,20 +35,39 @@ export class WelcomeComponent implements OnInit { } public createUser() { - this.WizardService.addOmbiConfig(this.config).subscribe(config => { - if(config != null) { - this.identityService.createWizardUser(this.localUser).subscribe(x => { - if (x.result) { - // save the config - this.router.navigate(["login"]); + if (this.config.applicationUrl) { + this.settingsService.verifyUrl(this.config.applicationUrl).subscribe(x => { + if (!x) { + this.notificationService.error(`The URL "${this.config.applicationUrl}" is not valid. Please format it correctly e.g. http://www.google.com/`); + this.stepper.selectedIndex = 3; + return; + } + this.saveConfig(); + }); } else { - if (x.errors.length > 0) { - this.notificationService.error(x.errors[0]); - this.stepper.previous(); - } + this.saveConfig(); } - }); } - }, configErr => this.notificationService.error(configErr)); + + private saveConfig() { + this.WizardService.addOmbiConfig(this.config).subscribe({ + next: (config) => { + if(config != null) { + this.identityService.createWizardUser(this.localUser).subscribe(x => { + if (x.result) { + // save the config + this.router.navigate(["login"]); + } else { + if (x.errors.length > 0) { + this.notificationService.error(x.errors[0]); + this.stepper.previous(); + } + } + }); + } + }, + error: (configErr) => this.notificationService.error(configErr) + }); } + } diff --git a/src/Ombi/Controllers/V1/SettingsController.cs b/src/Ombi/Controllers/V1/SettingsController.cs index abf1e86b7..fcd4bb1a4 100644 --- a/src/Ombi/Controllers/V1/SettingsController.cs +++ b/src/Ombi/Controllers/V1/SettingsController.cs @@ -334,6 +334,7 @@ namespace Ombi.Controllers.V1 [ApiExplorerSettings(IgnoreApi = true)] [HttpPost("customization/urlverify")] + [AllowAnonymous] public bool VerifyUrl([FromBody]UrlVerifyModel url) { return Uri.TryCreate(url.Url, UriKind.Absolute, out var __); From 033fa52fac13f14200f73c5368c30f1556512b8f Mon Sep 17 00:00:00 2001 From: tidusjar Date: Fri, 14 Jan 2022 10:52:02 +0000 Subject: [PATCH 15/20] chore(wizard): :recycle: Set the state when saving the wizard --- .../ClientApp/src/app/wizard/welcome/welcome.component.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.ts b/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.ts index ef29266d1..d1a9c59eb 100644 --- a/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.ts +++ b/src/Ombi/ClientApp/src/app/wizard/welcome/welcome.component.ts @@ -1,6 +1,7 @@ import { AfterViewInit, Component, OnInit, ViewChild } from "@angular/core"; import { IdentityService, NotificationService, SettingsService } from "../../services"; +import { CustomizationFacade } from "../../state/customization/customization.facade"; import { ICreateWizardUser } from "../../interfaces"; import { IOmbiConfigModel } from "../models/OmbiConfigModel"; import { MatHorizontalStepper } from'@angular/material/stepper'; @@ -19,7 +20,7 @@ export class WelcomeComponent implements OnInit { constructor(private router: Router, private identityService: IdentityService, private notificationService: NotificationService, private WizardService: WizardService, - private settingsService: SettingsService) { } + private settingsService: SettingsService, private customizationFacade: CustomizationFacade) { } public ngOnInit(): void { this.localUser = { @@ -55,6 +56,7 @@ export class WelcomeComponent implements OnInit { if(config != null) { this.identityService.createWizardUser(this.localUser).subscribe(x => { if (x.result) { + this.customizationFacade.loadCustomziationSettings().subscribe(); // save the config this.router.navigate(["login"]); } else { From 933b3892a236dc5af3c3d4a953bbc03a69601b39 Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Fri, 14 Jan 2022 14:01:10 +0100 Subject: [PATCH 16/20] chore: Fix broken automation test (#4471) --- tests/cypress/tests/search/search.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cypress/tests/search/search.spec.ts b/tests/cypress/tests/search/search.spec.ts index 12566d26f..a8aa3deb5 100644 --- a/tests/cypress/tests/search/search.spec.ts +++ b/tests/cypress/tests/search/search.spec.ts @@ -110,11 +110,11 @@ describe("Search Tests", () => { Page.navbar.searchFilter.tvToggle.click(); cy.wait('@searchResponse'); - const card = Page.getCard('2710', false); + const card = Page.getCard('131927', false); card.topLevelCard.realHover(); card.title.should('have.text', "Dexter: New Blood"); - card.overview.contains('Irish pub'); + card.overview.contains('Iron Lake'); card.requestType.contains('TV Show'); card.requestButton.should('exist'); }); From 7d47bbe92204855bf75d70b8fa548f9c3f3612bc Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Fri, 14 Jan 2022 14:02:24 +0100 Subject: [PATCH 17/20] fix: :bug: Add UI for Emby recently added cronjob settings (#4469) * Add UI for Emby recently added cronjob settings * Fix typo --- .../ClientApp/src/app/settings/jobs/jobs.component.html | 8 ++++++++ .../ClientApp/src/app/settings/jobs/jobs.component.ts | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html index 7e25704fa..e15a88b7f 100644 --- a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html +++ b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html @@ -86,6 +86,14 @@
+
+ + Emby Recently Added Sync + + The Emby Recently Added Sync is required + +
+
Jellyfin Sync diff --git a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts index 1e00d4e29..47d05776b 100644 --- a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts @@ -36,7 +36,7 @@ export class JobsComponent implements OnInit { retryRequests: [x.retryRequests, Validators.required], mediaDatabaseRefresh: [x.mediaDatabaseRefresh, Validators.required], autoDeleteRequests: [x.autoDeleteRequests, Validators.required], - EmbyRecentlyAddedSync: [x.embyRecentlyAddedSync, Validators.required], + embyRecentlyAddedSync: [x.embyRecentlyAddedSync, Validators.required], }); }); } From c5b7b673b1dee8334ff9f6ee3345ffb1b6266f6f Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Fri, 14 Jan 2022 13:04:41 +0000 Subject: [PATCH 18/20] chore(release): :rocket: v4.9.2 --- CHANGELOG.md | 20 +++++++++++--------- version.json | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea6e3359f..36dec9c46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +## [4.9.2](https://github.com/Ombi-app/Ombi/compare/v4.9.1...v4.9.2) (2022-01-14) + + +### Bug Fixes + +* :bug: Add UI for Emby recently added cronjob settings ([#4469](https://github.com/Ombi-app/Ombi/issues/4469)) ([7d47bbe](https://github.com/Ombi-app/Ombi/commit/7d47bbe92204855bf75d70b8fa548f9c3f3612bc)) +* **sonarr:** :bug: Fixed an issue where we could attempt to add a series to sonarr before sonarr has got all the metadata [#4459](https://github.com/Ombi-app/Ombi/issues/4459) ([5c691dc](https://github.com/Ombi-app/Ombi/commit/5c691dc98437a4cd24560ff625414fe05dd22f89)) +* **wizard:** :bug: Fixed the issue where the Application Url wasn't validated in the wizard ([33b8d11](https://github.com/Ombi-app/Ombi/commit/33b8d1111a1c6663d8c0bbd912be4660da7d013f)), closes [#4417](https://github.com/Ombi-app/Ombi/issues/4417) + + + ## [4.9.1](https://github.com/Ombi-app/Ombi/compare/v4.9.0...v4.9.1) (2022-01-14) @@ -172,12 +183,3 @@ -## [4.6.2](https://github.com/Ombi-app/Ombi/compare/v4.6.1...v4.6.2) (2021-11-10) - - -### Bug Fixes - -* **discover:** TV shows now display on the Actor Pages ([#4388](https://github.com/Ombi-app/Ombi/issues/4388)) ([6b716e7](https://github.com/Ombi-app/Ombi/commit/6b716e722076e3d1e6bf2097c5263645d5ea9edf)) - - - diff --git a/version.json b/version.json index 5d721d005..a3985a99d 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.9.1" + "version": "4.9.2" } \ No newline at end of file From 10cc0c0951f13221179516f8ff5c44dbecc9a0fd Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Fri, 14 Jan 2022 15:24:17 +0100 Subject: [PATCH 19/20] feat(notifications): :sparkles: Send new request email notifications to power users (#4462) * Send new request email notifications to power users * Send new request to power users as convention Remove option to toggle it off * Send New Request notification to power users in app * Better wording + fix mobile notifications --- .../Agents/DiscordNotification.cs | 5 ++-- .../Agents/EmailNotification.cs | 13 +++++++-- .../Agents/GotifyNotification.cs | 3 +- .../Agents/LegacyMobileNotification.cs | 26 +++++++++++------ .../Agents/MattermostNotification.cs | 3 +- .../Agents/MobileNotification.cs | 28 +++++++++++++------ .../Agents/PushbulletNotification.cs | 3 +- .../Agents/PushoverNotification.cs | 3 +- .../Agents/SlackNotification.cs | 3 +- .../Agents/TelegramNotification.cs | 3 +- .../Agents/WebhookNotification.cs | 3 +- .../Agents/WhatsAppNotification.cs | 3 +- src/Ombi.Notifications/BaseNotification.cs | 13 ++++++++- .../emailnotification.component.html | 2 +- 14 files changed, 80 insertions(+), 31 deletions(-) diff --git a/src/Ombi.Notifications/Agents/DiscordNotification.cs b/src/Ombi.Notifications/Agents/DiscordNotification.cs index 0cc0c9b89..ae344116f 100644 --- a/src/Ombi.Notifications/Agents/DiscordNotification.cs +++ b/src/Ombi.Notifications/Agents/DiscordNotification.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using Ombi.Api.Discord; using Ombi.Api.Discord.Models; @@ -21,8 +22,8 @@ namespace Ombi.Notifications.Agents public DiscordNotification(IDiscordApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository sub, IMusicRequestRepository music, - IRepository userPref) - : base(sn, r, m, t, s, log, sub, music, userPref) + IRepository userPref, UserManager um) + : base(sn, r, m, t, s, log, sub, music, userPref, um) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/EmailNotification.cs b/src/Ombi.Notifications/Agents/EmailNotification.cs index f41406d0e..cb96fcdb6 100644 --- a/src/Ombi.Notifications/Agents/EmailNotification.cs +++ b/src/Ombi.Notifications/Agents/EmailNotification.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using MailKit.Net.Smtp; @@ -22,7 +23,7 @@ namespace Ombi.Notifications.Agents { public EmailNotification(ISettingsService settings, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, IEmailProvider prov, ISettingsService c, ILogger log, UserManager um, IRepository sub, IMusicRequestRepository music, - IRepository userPref) : base(settings, r, m, t, c, log, sub, music, userPref) + IRepository userPref) : base(settings, r, m, t, c, log, sub, music, userPref, um) { EmailProvider = prov; Logger = log; @@ -114,7 +115,15 @@ namespace Ombi.Notifications.Agents var plaintext = await LoadPlainTextMessage(NotificationType.NewRequest, model, settings); message.Other.Add("PlainTextBody", plaintext); - await Send(message, settings); + foreach (var recipient in (await GetPrivilegedUsers()).DistinctBy(x => x.Email)) + { + if (recipient.Email.IsNullOrEmpty()) + { + continue; + } + message.To = recipient.Email; + await Send(message, settings); + } } protected override async Task NewIssue(NotificationOptions model, EmailNotificationSettings settings) diff --git a/src/Ombi.Notifications/Agents/GotifyNotification.cs b/src/Ombi.Notifications/Agents/GotifyNotification.cs index 00b62c343..e948c4d89 100644 --- a/src/Ombi.Notifications/Agents/GotifyNotification.cs +++ b/src/Ombi.Notifications/Agents/GotifyNotification.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using Ombi.Api.Gotify; using Ombi.Core.Settings; @@ -17,7 +18,7 @@ namespace Ombi.Notifications.Agents { public GotifyNotification(IGotifyApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository sub, IMusicRequestRepository music, - IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) + IRepository userPref, UserManager um) : base(sn, r, m, t, s, log, sub, music, userPref, um) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/LegacyMobileNotification.cs b/src/Ombi.Notifications/Agents/LegacyMobileNotification.cs index c2d71e0d0..9df7c6a94 100644 --- a/src/Ombi.Notifications/Agents/LegacyMobileNotification.cs +++ b/src/Ombi.Notifications/Agents/LegacyMobileNotification.cs @@ -23,7 +23,7 @@ namespace Ombi.Notifications.Agents public LegacyMobileNotification(IOneSignalApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository notification, UserManager um, IRepository sub, IMusicRequestRepository music, IRepository issueRepository, - IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) + IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref, um) { _api = api; _logger = log; @@ -59,7 +59,7 @@ namespace Ombi.Notifications.Agents }; // Get admin devices - var playerIds = await GetAdmins(NotificationType.NewRequest); + var playerIds = await GetPrivilegedUsersPlayerIds(); await Send(playerIds, notification, settings, model, true); } @@ -77,7 +77,7 @@ namespace Ombi.Notifications.Agents }; // Get admin devices - var playerIds = await GetAdmins(NotificationType.Issue); + var playerIds = await GetAdmins(); await Send(playerIds, notification, settings, model); } @@ -106,7 +106,7 @@ namespace Ombi.Notifications.Agents else { // Send to admin - var playerIds = await GetAdmins(NotificationType.IssueComment); + var playerIds = await GetAdmins(); await Send(playerIds, notification, settings, model); } } @@ -147,7 +147,7 @@ namespace Ombi.Notifications.Agents }; // Get admin devices - var playerIds = await GetAdmins(NotificationType.Test); + var playerIds = await GetAdmins(); await Send(playerIds, notification, settings, model); } @@ -241,15 +241,25 @@ namespace Ombi.Notifications.Agents await Send(playerIds, notification, settings, model); } - private async Task> GetAdmins(NotificationType type) + private async Task> GetAdmins() { - var adminUsers = (await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin)).Select(x => x.Id).ToList(); + return await GetNotificationRecipients(await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin)); + } + private async Task> GetPrivilegedUsersPlayerIds() + { + return await GetNotificationRecipients(await GetPrivilegedUsers()); + } + + private async Task> GetNotificationRecipients(IEnumerable users) + { + + var adminUsers = users.Select(x => x.Id).ToList(); var notificationUsers = _notifications.GetAll().Include(x => x.User).Where(x => adminUsers.Contains(x.UserId)); var playerIds = await notificationUsers.Select(x => x.PlayerId).ToListAsync(); if (!playerIds.Any()) { _logger.LogInformation( - $"there are no admins to send a notification for {type}, for agent {NotificationAgent.Mobile}"); + $"there are no users to send a notification for agent {NotificationAgent.Mobile}"); return null; } return playerIds; diff --git a/src/Ombi.Notifications/Agents/MattermostNotification.cs b/src/Ombi.Notifications/Agents/MattermostNotification.cs index 39e87e334..4b5b570c7 100644 --- a/src/Ombi.Notifications/Agents/MattermostNotification.cs +++ b/src/Ombi.Notifications/Agents/MattermostNotification.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using Ombi.Api.Mattermost; using Ombi.Api.Mattermost.Models; @@ -19,7 +20,7 @@ namespace Ombi.Notifications.Agents { public MattermostNotification(IMattermostApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository sub, IMusicRequestRepository music, - IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) + IRepository userPref, UserManager um) : base(sn, r, m, t, s, log, sub, music, userPref, um) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/MobileNotification.cs b/src/Ombi.Notifications/Agents/MobileNotification.cs index b7ada4838..0d21f39a5 100644 --- a/src/Ombi.Notifications/Agents/MobileNotification.cs +++ b/src/Ombi.Notifications/Agents/MobileNotification.cs @@ -23,7 +23,7 @@ namespace Ombi.Notifications.Agents public MobileNotification(ICloudMobileNotification api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository notification, UserManager um, IRepository sub, IMusicRequestRepository music, IRepository issueRepository, - IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) + IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref, um) { _api = api; _logger = log; @@ -62,7 +62,7 @@ namespace Ombi.Notifications.Agents }; // Get admin devices - var playerIds = await GetAdmins(NotificationType.NewRequest); + var playerIds = await GetPrivilegedUsersPlayerIds(); await Send(playerIds, notification, settings, model, true); } @@ -82,7 +82,7 @@ namespace Ombi.Notifications.Agents }; // Get admin devices - var playerIds = await GetAdmins(NotificationType.Issue); + var playerIds = await GetAdmins(); await Send(playerIds, notification, settings, model); } @@ -112,7 +112,7 @@ namespace Ombi.Notifications.Agents else { // Send to admin - var playerIds = await GetAdmins(NotificationType.IssueComment); + var playerIds = await GetAdmins(); await Send(playerIds, notification, settings, model); } } @@ -157,7 +157,7 @@ namespace Ombi.Notifications.Agents }; // Get admin devices - var playerIds = await GetAdmins(NotificationType.Test); + var playerIds = await GetAdmins(); await Send(playerIds, notification, settings, model); } @@ -279,15 +279,25 @@ namespace Ombi.Notifications.Agents await Send(playerIds, notification, settings, model); } - private async Task> GetAdmins(NotificationType type) + private async Task> GetAdmins() { - var adminUsers = (await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin)).Select(x => x.Id).ToList(); + return await GetNotificationRecipients(await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin)); + } + private async Task> GetPrivilegedUsersPlayerIds() + { + return await GetNotificationRecipients(await GetPrivilegedUsers()); + } + + private async Task> GetNotificationRecipients(IEnumerable users) + { + + var adminUsers = users.Select(x => x.Id).ToList(); var notificationUsers = _notifications.GetAll().Include(x => x.User).Where(x => adminUsers.Contains(x.UserId)); var playerIds = await notificationUsers.Select(x => x.Token).ToListAsync(); if (!playerIds.Any()) { _logger.LogInformation( - $"there are no admins to send a notification for {type}, for agent {NotificationAgent.Mobile}"); + $"there are no users to send a notification for agent {NotificationAgent.Mobile}"); return null; } return playerIds; @@ -377,7 +387,7 @@ namespace Ombi.Notifications.Agents }; // Get admin devices - var playerIds = await GetAdmins(NotificationType.PartiallyAvailable); + var playerIds = await GetAdmins(); await Send(playerIds, notification, settings, model, true); } } diff --git a/src/Ombi.Notifications/Agents/PushbulletNotification.cs b/src/Ombi.Notifications/Agents/PushbulletNotification.cs index fd4be12a2..3823afe13 100644 --- a/src/Ombi.Notifications/Agents/PushbulletNotification.cs +++ b/src/Ombi.Notifications/Agents/PushbulletNotification.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using Ombi.Api.Pushbullet; using Ombi.Core.Settings; @@ -17,7 +18,7 @@ namespace Ombi.Notifications.Agents { public PushbulletNotification(IPushbulletApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository sub, IMusicRequestRepository music, - IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) + IRepository userPref, UserManager um) : base(sn, r, m, t, s, log, sub, music, userPref, um) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/PushoverNotification.cs b/src/Ombi.Notifications/Agents/PushoverNotification.cs index 21352b8d6..3edcd62e2 100644 --- a/src/Ombi.Notifications/Agents/PushoverNotification.cs +++ b/src/Ombi.Notifications/Agents/PushoverNotification.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using Ombi.Api.Pushbullet; using Ombi.Api.Pushover; @@ -18,7 +19,7 @@ namespace Ombi.Notifications.Agents { public PushoverNotification(IPushoverApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository sub, IMusicRequestRepository music, - IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) + IRepository userPref, UserManager um) : base(sn, r, m, t, s, log, sub, music, userPref, um) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/SlackNotification.cs b/src/Ombi.Notifications/Agents/SlackNotification.cs index 8dbf14a7d..7ea5b628a 100644 --- a/src/Ombi.Notifications/Agents/SlackNotification.cs +++ b/src/Ombi.Notifications/Agents/SlackNotification.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using Ombi.Api.Slack; using Ombi.Api.Slack.Models; @@ -18,7 +19,7 @@ namespace Ombi.Notifications.Agents { public SlackNotification(ISlackApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository sub, IMusicRequestRepository music, - IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) + IRepository userPref, UserManager um) : base(sn, r, m, t, s, log, sub, music, userPref, um) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/TelegramNotification.cs b/src/Ombi.Notifications/Agents/TelegramNotification.cs index 6561a2494..7d5d9ea54 100644 --- a/src/Ombi.Notifications/Agents/TelegramNotification.cs +++ b/src/Ombi.Notifications/Agents/TelegramNotification.cs @@ -10,6 +10,7 @@ using Ombi.Store.Entities; using Ombi.Store.Repository; using Ombi.Store.Repository.Requests; using Ombi.Api.Telegram; +using Microsoft.AspNetCore.Identity; namespace Ombi.Notifications.Agents { @@ -19,7 +20,7 @@ namespace Ombi.Notifications.Agents INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s , IRepository sub, IMusicRequestRepository music, - IRepository userPref) : base(sn, r, m, t,s,log, sub, music, userPref) + IRepository userPref, UserManager um) : base(sn, r, m, t,s,log, sub, music, userPref, um) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/WebhookNotification.cs b/src/Ombi.Notifications/Agents/WebhookNotification.cs index c226d048a..6ed62605e 100644 --- a/src/Ombi.Notifications/Agents/WebhookNotification.cs +++ b/src/Ombi.Notifications/Agents/WebhookNotification.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using Ombi.Api.Webhook; using Ombi.Core.Settings; @@ -18,7 +19,7 @@ namespace Ombi.Notifications.Agents { public WebhookNotification(IWebhookApi api, ISettingsService sn, ILogger log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s, IRepository sub, IMusicRequestRepository music, - IRepository userPref) : base(sn, r, m, t, s, log, sub, music, userPref) + IRepository userPref, UserManager um) : base(sn, r, m, t, s, log, sub, music, userPref, um) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/Agents/WhatsAppNotification.cs b/src/Ombi.Notifications/Agents/WhatsAppNotification.cs index cf97f498f..7956af18a 100644 --- a/src/Ombi.Notifications/Agents/WhatsAppNotification.cs +++ b/src/Ombi.Notifications/Agents/WhatsAppNotification.cs @@ -10,6 +10,7 @@ using Ombi.Store.Entities; using Ombi.Store.Repository; using Ombi.Store.Repository.Requests; using Ombi.Api.Twilio; +using Microsoft.AspNetCore.Identity; namespace Ombi.Notifications.Agents { @@ -19,7 +20,7 @@ namespace Ombi.Notifications.Agents INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService s , IRepository sub, IMusicRequestRepository music, - IRepository userPref) : base(sn, r, m, t,s,log, sub, music, userPref) + IRepository userPref, UserManager um) : base(sn, r, m, t,s,log, sub, music, userPref, um) { Api = api; Logger = log; diff --git a/src/Ombi.Notifications/BaseNotification.cs b/src/Ombi.Notifications/BaseNotification.cs index ac9de5736..9397767bf 100644 --- a/src/Ombi.Notifications/BaseNotification.cs +++ b/src/Ombi.Notifications/BaseNotification.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Ombi.Core.Settings; @@ -19,7 +21,7 @@ namespace Ombi.Notifications { protected BaseNotification(ISettingsService settings, INotificationTemplatesRepository templateRepo, IMovieRequestRepository movie, ITvRequestRepository tv, ISettingsService customization, ILogger> log, IRepository sub, IMusicRequestRepository album, - IRepository notificationUserPreferences) + IRepository notificationUserPreferences, UserManager um) { Settings = settings; TemplateRepository = templateRepo; @@ -30,6 +32,7 @@ namespace Ombi.Notifications _log = log; AlbumRepository = album; UserNotificationPreferences = notificationUserPreferences; + _userManager = um; Settings.ClearCache(); } @@ -43,6 +46,7 @@ namespace Ombi.Notifications protected IRepository UserNotificationPreferences { get; set; } private ISettingsService CustomizationSettings { get; } private readonly ILogger> _log; + private readonly UserManager _userManager; protected ChildRequests TvRequest { get; set; } @@ -210,6 +214,13 @@ namespace Ombi.Notifications .FirstOrDefault(x => x.Agent == agent && x.UserId == userId); } + protected async Task> GetPrivilegedUsers() + { + IEnumerable recipients = await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin); + recipients = recipients.Concat(await _userManager.GetUsersInRoleAsync(OmbiRoles.PowerUser)); + return recipients; + } + private NotificationMessageContent Parse(NotificationOptions model, NotificationTemplates template, NotificationAgent agent) { var resolver = new NotificationMessageResolver(); diff --git a/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.html b/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.html index 33aa3a06c..5c24d21f2 100644 --- a/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.html +++ b/src/Ombi/ClientApp/src/app/settings/notifications/emailnotification.component.html @@ -61,7 +61,7 @@
Admin Email - + Admin Email is required From 70c7f0534c0815db8dc8e72f614fc86564370668 Mon Sep 17 00:00:00 2001 From: Conventional Changelog Action Date: Fri, 14 Jan 2022 14:27:59 +0000 Subject: [PATCH 20/20] chore(release): :rocket: v4.10.0 --- CHANGELOG.md | 20 +++++++++----------- version.json | 2 +- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36dec9c46..1ea8fe031 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# [4.10.0](https://github.com/Ombi-app/Ombi/compare/v4.9.2...v4.10.0) (2022-01-14) + + +### Features + +* **notifications:** :sparkles: Send new request email notifications to power users ([#4462](https://github.com/Ombi-app/Ombi/issues/4462)) ([10cc0c0](https://github.com/Ombi-app/Ombi/commit/10cc0c0951f13221179516f8ff5c44dbecc9a0fd)) + + + ## [4.9.2](https://github.com/Ombi-app/Ombi/compare/v4.9.1...v4.9.2) (2022-01-14) @@ -172,14 +181,3 @@ -## [4.6.3](https://github.com/Ombi-app/Ombi/compare/v4.6.2...v4.6.3) (2021-11-11) - - -### Bug Fixes - -* **discover:** :bug: Display TV + movies on actor page in user language ([#4395](https://github.com/Ombi-app/Ombi/issues/4395)) ([fe635c7](https://github.com/Ombi-app/Ombi/commit/fe635c7106bc487ff879bdc8a73bab16cb389b97)) -* **permissions:** :bug: Improved the security around the role "Manage Own Requests" ([#4397](https://github.com/Ombi-app/Ombi/issues/4397)) ([334a32b](https://github.com/Ombi-app/Ombi/commit/334a32bca42f90198d9b720d2bdb710a583be47f)), closes [#4391](https://github.com/Ombi-app/Ombi/issues/4391) -* **search:** Fixed some cases where search wouldn't work correctly ([#4398](https://github.com/Ombi-app/Ombi/issues/4398)) ([4410790](https://github.com/Ombi-app/Ombi/commit/4410790bc096826bc11554098f846e3acb59589a)) - - - diff --git a/version.json b/version.json index a3985a99d..8e1cf1a5b 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "4.9.2" + "version": "4.10.0" } \ No newline at end of file