pull/3895/head
tidusjar 6 years ago
commit e77d54c6d1

@ -1,48 +0,0 @@
<!---
!! Please use the Support / bug report template, otherwise we will close the Github issue !!
Version 2.X is not supported anymore. Please don't open a issue for the 2.x version.
See https://github.com/tidusjar/Ombi/issues/1455 for more information.
(Pleas submit a feature request over here: http://feathub.com/tidusjar/Ombi)
--->
#### Ombi build Version:
V 3.0.XX
#### Update Branch:
Open Beta
#### Media Sever:
Plex/Emby
#### Media Server Version:
<!-- If appropriate --->
#### Operating System:
(Place text here)
#### Ombi Applicable Logs (from `/logs/` directory or the Admin page):
```
(Logs go here. Don't remove the ' tags for showing your logs correctly. Please make sure you remove any personal information from the logs)
```
#### Problem Description:
(Place text here)
#### Reproduction Steps:
Please include any steps to reproduce the issue, this the request that is causing the problem etc.

@ -0,0 +1,37 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Logs (Logs directory where Ombi is located)**
If applicable, a snippet of the logs that seems relevant to the bug if present.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
**Ombi Version (please complete the following information):**
- Version [e.g. 3.0.1158]
- Media Server [e.g. Plex]
**Additional context**
Add any other context about the problem here.

@ -1,14 +1,9 @@
# Changelog # Changelog
## (unreleased)
### **New Features** ## v3.0.4119 (2019-1-09)
- Added new classes to the posters #2732. [TidusJar]
## v3.0.4119 (2019-01-09)
### **New Features** ### **New Features**
- Update CHANGELOG.md. [Jamie] - Update CHANGELOG.md. [Jamie]
@ -29,33 +24,27 @@
- Added the ability to specify a year when searching for movies. [tidusjar] - Added the ability to specify a year when searching for movies. [tidusjar]
- Update NewsletterTemplate.html. [d1slact0r] - Made the newsletter use the default lanuage code set in the Ombi settings for movie information. [TidusJar]
- Update NewsletterTemplate.html. [d1slact0r]
- Update NewsletterTemplate.html. [d1slact0r]
- Update HtmlTemplateGenerator.cs. [d1slact0r]
- Update NewsletterTemplate.html. [d1slact0r]
- Update HtmlTemplateGenerator.cs. [d1slact0r] - Added a global language flag that now applies to the search by default. [tidusjar]
- Update NewsletterTemplate.html. [d1slact0r] - Updated the frontend packages (Using Angular 7 now) [TidusJar]
- Update NewsletterTemplate.html. [d1slact0r] - Added capture of anonymous analytical data. [tidusjar]
- Update NewsletterTemplate.html. [d1slact0r] - Added {AvailableDate} as a Notification Variable, this is the date the request was marked as available. See here: https://github.com/tidusjar/Ombi/wiki/Notification-Template-Variables. [tidusjar]
- Update HtmlTemplateGenerator.cs. [d1slact0r] - Updated the Newsletter template! Better mail client support [d1slact0r]
- Updated boostrap #2694. [Jamie] - Updated boostrap #2694. [TidusJar]
- Added the ability to deny a request with a reason. [TidusJar] - Added the ability to deny a request with a reason. [TidusJar]
- Updated to .net core 2.2 and included a linux-arm64 build. [aptalca]
- Make the newsletter BCC the users rather than creating a million newsletters (Hopefully will stop SMTP providers from marking as spam). This does mean that the custom user customization in the newsletter will no longer work. [TidusJar]
- Update EmbyEpisodeSync.cs. [Jamie]
- Updated to .net core 2.2 and included a linux-arm64 build. [TidusJar] - New translations [TidusJar]
### **Fixes** ### **Fixes**
@ -77,62 +66,12 @@
- Fixed #2716. [tidusjar] - Fixed #2716. [tidusjar]
- Make the newsletter BCC the users rather than creating a million newsletters (Hopefully will stop SMTP providers from marking as spam). This does mean that the custom user customization in the newsletter will no longer work. [TidusJar]
- If we don't know the Plex agent, then see if it's a ImdbId, if it's not check the string for any episode and season hints #2695. [tidusjar] - If we don't know the Plex agent, then see if it's a ImdbId, if it's not check the string for any episode and season hints #2695. [tidusjar]
- New translations en.json (Swedish) [Jamie]
- New translations en.json (Spanish) [Jamie]
- New translations en.json (Portuguese, Brazilian) [Jamie]
- New translations en.json (Polish) [Jamie]
- New translations en.json (Norwegian) [Jamie]
- New translations en.json (Italian) [Jamie]
- New translations en.json (German) [Jamie]
- New translations en.json (French) [Jamie]
- New translations en.json (Dutch) [Jamie]
- New translations en.json (Danish) [Jamie]
- New translations en.json (Dutch) [Jamie]
- New translations en.json (Dutch) [Jamie]
- New translations en.json (Dutch) [Jamie]
- Made the search results the language specified in the search refinement. [tidusjar]
- Fixed #2704. [tidusjar] - Fixed #2704. [tidusjar]
- Now it is fixed :) [d1slact0r]
- Android please be nice now. [d1slact0r]
- Fixed title bit better. [d1slact0r]
- Fixed titles. [d1slact0r]
- This should fix the build for sure (stupid quotes) [d1slact0r]
- Fixes build. [d1slact0r]
- Rewritten the whole newsletter template. [d1slact0r]
- Fixed #2697. [tidusjar] - Fixed #2697. [tidusjar]
- Add linux-arm runtime identifier. [aptalca]
- Add back arm packages. [aptalca]
- Add arm32 package. [aptalca]
- Fixed #2691. [tidusjar] - Fixed #2691. [tidusjar]
- Fixed linting. [TidusJar] - Fixed linting. [TidusJar]
@ -141,13 +80,10 @@
- Fixed #2678. [TidusJar] - Fixed #2678. [TidusJar]
- Deny reason for movie requests. [TidusJar]
- Set the landing and login pages background refresh to 15 seconds rather than 10 and 7. [TidusJar] - Set the landing and login pages background refresh to 15 seconds rather than 10 and 7. [TidusJar]
- Fixed a bug with us thinking future dated emby episodes are not available, Consoldated the emby and plex search rules (since they have the same logic) [TidusJar] - Fixed a bug with us thinking future dated emby episodes are not available, Consoldated the emby and plex search rules (since they have the same logic) [TidusJar]
- Fixed build. [TidusJar]
## v3.0.4036 (2018-12-11) ## v3.0.4036 (2018-12-11)

@ -117,13 +117,12 @@ Please feel free to submit a pull request!
# Donation # Donation
If you feel like donating you can donate with the below buttons! If you feel like donating you can donate with the below buttons!
[![Patreon](https://www.ombi.io/img/patreondonate.svg)](https://patreon.com/tidusjar/Ombi)
[![Paypal](https://www.ombi.io/img/paypaldonate.svg)](https://paypal.me/PlexRequestsNet) [![Patreon](https://img.shields.io/badge/patreon-donate-yellow.svg)](https://patreon.com/tidusjar/Ombi)
[![Paypal](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://paypal.me/PlexRequestsNet)
### A massive thanks to everyone for all their help! ### A massive thanks to everyone for all their help!
## Stats
[![Throughput Graph](https://graphs.waffle.io/tidusjar/PlexRequests.Net/throughput.svg)](https://waffle.io/tidusjar/PlexRequests.Net/metrics/throughput)
### Sponsors ### ### Sponsors ###
- [JetBrains](http://www.jetbrains.com/) for providing us with free licenses to their great tools - [JetBrains](http://www.jetbrains.com/) for providing us with free licenses to their great tools

@ -385,6 +385,7 @@ namespace Ombi.Core.Engine
foreach (var ep in s.Episodes) foreach (var ep in s.Episodes)
{ {
ep.Approved = true; ep.Approved = true;
ep.Requested = true;
} }
} }

@ -99,7 +99,7 @@ namespace Ombi.Core.Engine
{ {
Url = e.url, Url = e.url,
Title = e.name, Title = e.name,
AirDate = DateTime.Parse(e.airstamp ?? DateTime.MinValue.ToString()), AirDate = e.airstamp.HasValue() ? DateTime.Parse(e.airstamp) : DateTime.MinValue,
EpisodeNumber = e.number, EpisodeNumber = e.number,
}); });
@ -112,7 +112,7 @@ namespace Ombi.Core.Engine
{ {
Url = e.url, Url = e.url,
Title = e.name, Title = e.name,
AirDate = DateTime.Parse(e.airstamp ?? DateTime.MinValue.ToString()), AirDate = e.airstamp.HasValue() ? DateTime.Parse(e.airstamp) : DateTime.MinValue,
EpisodeNumber = e.number, EpisodeNumber = e.number,
}); });
} }

@ -1,4 +1,5 @@
using System.Linq; using System;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Ombi.Core.Models.Search; using Ombi.Core.Models.Search;
@ -87,11 +88,11 @@ namespace Ombi.Core.Rule.Rules.Search
} }
} }
if (request.SeasonRequests.Any() && request.SeasonRequests.All(x => x.Episodes.All(e => e.Available))) if (request.SeasonRequests.Any() && request.SeasonRequests.All(x => x.Episodes.All(e => e.Available && e.AirDate > DateTime.MinValue)))
{ {
request.FullyAvailable = true; request.FullyAvailable = true;
} }
if (request.SeasonRequests.Any() && request.SeasonRequests.All(x => x.Episodes.Any(e => e.Available))) if (request.SeasonRequests.Any() && request.SeasonRequests.All(x => x.Episodes.Any(e => e.Available && e.AirDate > DateTime.MinValue)))
{ {
request.PartlyAvailable = true; request.PartlyAvailable = true;
} }

@ -49,7 +49,6 @@ namespace Ombi.Core.Senders
{ {
try try
{ {
var cpSettings = await CouchPotatoSettings.GetSettingsAsync(); var cpSettings = await CouchPotatoSettings.GetSettingsAsync();
//var watcherSettings = await WatcherSettings.GetSettingsAsync(); //var watcherSettings = await WatcherSettings.GetSettingsAsync();
var radarrSettings = await RadarrSettings.GetSettingsAsync(); var radarrSettings = await RadarrSettings.GetSettingsAsync();
@ -76,7 +75,7 @@ namespace Ombi.Core.Senders
} }
catch (Exception e) catch (Exception e)
{ {
Log.LogError(e, "Error when seing movie to DVR app, added to the request queue"); Log.LogError(e, "Error when sending movie to DVR app, added to the request queue");
// Check if already in request quee // Check if already in request quee
var existingQueue = await _requestQueuRepository.FirstOrDefaultAsync(x => x.RequestId == model.Id); var existingQueue = await _requestQueuRepository.FirstOrDefaultAsync(x => x.RequestId == model.Id);

@ -16,6 +16,7 @@ using Ombi.Settings.Settings.Models.External;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository; using Ombi.Store.Repository;
using Remotion.Linq.Parsing.Structure.IntermediateModel;
namespace Ombi.Core.Senders namespace Ombi.Core.Senders
{ {
@ -57,7 +58,7 @@ namespace Ombi.Core.Senders
var sonarr = await SonarrSettings.GetSettingsAsync(); var sonarr = await SonarrSettings.GetSettingsAsync();
if (sonarr.Enabled) if (sonarr.Enabled)
{ {
var result = await SendToSonarr(model); var result = await SendToSonarr(model, sonarr);
if (result != null) if (result != null)
{ {
return new SenderResult return new SenderResult
@ -109,7 +110,7 @@ namespace Ombi.Core.Senders
catch (Exception e) catch (Exception e)
{ {
Logger.LogError(e, "Exception thrown when sending a movie to DVR app, added to the request queue"); Logger.LogError(e, "Exception thrown when sending a movie to DVR app, added to the request queue");
// Check if already in request quee // Check if already in request queue
var existingQueue = await _requestQueueRepository.FirstOrDefaultAsync(x => x.RequestId == model.Id); var existingQueue = await _requestQueueRepository.FirstOrDefaultAsync(x => x.RequestId == model.Id);
if (existingQueue != null) if (existingQueue != null)
{ {
@ -134,7 +135,7 @@ namespace Ombi.Core.Senders
return new SenderResult return new SenderResult
{ {
Success = false, Success = false,
Message = "Something wen't wrong!" Message = "Something went wrong!"
}; };
} }
@ -150,13 +151,8 @@ namespace Ombi.Core.Senders
/// <param name="s"></param> /// <param name="s"></param>
/// <param name="model"></param> /// <param name="model"></param>
/// <returns></returns> /// <returns></returns>
public async Task<NewSeries> SendToSonarr(ChildRequests model) public async Task<NewSeries> SendToSonarr(ChildRequests model, SonarrSettings s)
{ {
var s = await SonarrSettings.GetSettingsAsync();
if (!s.Enabled)
{
return null;
}
if (string.IsNullOrEmpty(s.ApiKey)) if (string.IsNullOrEmpty(s.ApiKey))
{ {
return null; return null;
@ -319,10 +315,19 @@ namespace Ombi.Core.Senders
foreach (var season in model.SeasonRequests) foreach (var season in model.SeasonRequests)
{ {
var sonarrSeason = sonarrEpList.Where(x => x.seasonNumber == season.SeasonNumber); var sonarrEpisodeList = sonarrEpList.Where(x => x.seasonNumber == season.SeasonNumber).ToList();
var sonarrEpCount = sonarrSeason.Count(); var sonarrEpCount = sonarrEpisodeList.Count;
var ourRequestCount = season.Episodes.Count; var ourRequestCount = season.Episodes.Count;
var ourEpisodes = season.Episodes.Select(x => x.EpisodeNumber).ToList();
var unairedEpisodes = sonarrEpisodeList.Where(x => x.airDateUtc > DateTime.UtcNow).Select(x => x.episodeNumber).ToList();
//// Check if we have requested all the latest episodes, if we have then monitor
//// 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 existingSeason = var existingSeason =
result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber); result.seasons.FirstOrDefault(x => x.seasonNumber == season.SeasonNumber);
if (existingSeason == null) if (existingSeason == null)
@ -332,7 +337,7 @@ namespace Ombi.Core.Senders
} }
if (sonarrEpCount == ourRequestCount) if (sonarrEpCount == ourRequestCount /*|| !missingEpisodes.Any()*/)
{ {
// We have the same amount of requests as all of the episodes in the season. // We have the same amount of requests as all of the episodes in the season.

@ -26,8 +26,6 @@ namespace Ombi.Notifications
MovieRepository = movie; MovieRepository = movie;
TvRepository = tv; TvRepository = tv;
CustomizationSettings = customization; CustomizationSettings = customization;
Settings.ClearCache();
CustomizationSettings.ClearCache();
RequestSubscription = sub; RequestSubscription = sub;
_log = log; _log = log;
AlbumRepository = album; AlbumRepository = album;
@ -55,14 +53,12 @@ namespace Ombi.Notifications
public async Task NotifyAsync(NotificationOptions model) public async Task NotifyAsync(NotificationOptions model)
{ {
Settings.ClearCache();
var configuration = await GetConfiguration(); var configuration = await GetConfiguration();
await NotifyAsync(model, configuration); await NotifyAsync(model, configuration);
} }
public async Task NotifyAsync(NotificationOptions model, Settings.Settings.Models.Settings settings) public async Task NotifyAsync(NotificationOptions model, Settings.Settings.Models.Settings settings)
{ {
Settings.ClearCache();
if (settings == null) await NotifyAsync(model); if (settings == null) await NotifyAsync(model);
var notificationSettings = (T)settings; var notificationSettings = (T)settings;

@ -5,6 +5,7 @@ using MailKit.Net.Smtp;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using MimeKit; using MimeKit;
using Ombi.Core.Settings; using Ombi.Core.Settings;
using Ombi.Helpers;
using Ombi.Notifications.Models; using Ombi.Notifications.Models;
using Ombi.Notifications.Templates; using Ombi.Notifications.Templates;
using Ombi.Settings.Settings.Models; using Ombi.Settings.Settings.Models;
@ -56,6 +57,11 @@ namespace Ombi.Notifications
using (var client = new SmtpClient()) using (var client = new SmtpClient())
{ {
if (customization.ApplicationUrl.HasValue())
{
client.LocalDomain = customization.ApplicationUrl;
}
if (settings.DisableCertificateChecking) if (settings.DisableCertificateChecking)
{ {
// Disable validation of the certificate associated with the SMTP service // Disable validation of the certificate associated with the SMTP service

@ -28,7 +28,6 @@ namespace Ombi.Schedule.Jobs.Emby
_repo = repo; _repo = repo;
_episodeSync = epSync; _episodeSync = epSync;
_metadata = metadata; _metadata = metadata;
_settings.ClearCache();
} }
private readonly ILogger<EmbyContentSync> _logger; private readonly ILogger<EmbyContentSync> _logger;

@ -49,7 +49,6 @@ namespace Ombi.Schedule.Jobs.Emby
_settings = s; _settings = s;
_repo = repo; _repo = repo;
_avaliabilityChecker = checker; _avaliabilityChecker = checker;
_settings.ClearCache();
} }
private readonly ISettingsService<EmbySettings> _settings; private readonly ISettingsService<EmbySettings> _settings;

@ -50,8 +50,6 @@ namespace Ombi.Schedule.Jobs.Emby
_log = log; _log = log;
_embySettings = embySettings; _embySettings = embySettings;
_userManagementSettings = ums; _userManagementSettings = ums;
_userManagementSettings.ClearCache();
_embySettings.ClearCache();
} }
private readonly IEmbyApi _api; private readonly IEmbyApi _api;

@ -1,19 +1,16 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire; using Hangfire;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Api.Lidarr; using Ombi.Api.Lidarr;
using Ombi.Api.Radarr;
using Ombi.Core.Settings; using Ombi.Core.Settings;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Settings.Settings.Models.External; using Ombi.Settings.Settings.Models.External;
using Ombi.Store.Context; using Ombi.Store.Context;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Serilog;
using ILogger = Microsoft.Extensions.Logging.ILogger; using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace Ombi.Schedule.Jobs.Lidarr namespace Ombi.Schedule.Jobs.Lidarr
@ -29,7 +26,6 @@ namespace Ombi.Schedule.Jobs.Lidarr
_ctx = ctx; _ctx = ctx;
_job = job; _job = job;
_availability = availability; _availability = availability;
_lidarrSettings.ClearCache();
} }
private readonly ISettingsService<LidarrSettings> _lidarrSettings; private readonly ISettingsService<LidarrSettings> _lidarrSettings;

@ -1,19 +1,16 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire; using Hangfire;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Api.Lidarr; using Ombi.Api.Lidarr;
using Ombi.Api.Radarr;
using Ombi.Core.Settings; using Ombi.Core.Settings;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Settings.Settings.Models.External; using Ombi.Settings.Settings.Models.External;
using Ombi.Store.Context; using Ombi.Store.Context;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Serilog;
using ILogger = Microsoft.Extensions.Logging.ILogger; using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace Ombi.Schedule.Jobs.Lidarr namespace Ombi.Schedule.Jobs.Lidarr
@ -29,7 +26,6 @@ namespace Ombi.Schedule.Jobs.Lidarr
_ctx = ctx; _ctx = ctx;
_job = background; _job = background;
_albumSync = album; _albumSync = album;
_lidarrSettings.ClearCache();
} }
private readonly ISettingsService<LidarrSettings> _lidarrSettings; private readonly ISettingsService<LidarrSettings> _lidarrSettings;

@ -28,9 +28,9 @@ namespace Ombi.Schedule.Jobs.Ombi
return; return;
} }
var now = DateTime.Now.AddDays(-settings.DaysAfterResolvedToDelete).Date; var deletionDate = DateTime.Now.AddDays(settings.DaysAfterResolvedToDelete).Date;
var resolved = _issuesRepository.GetAll().Where(x => x.Status == IssueStatus.Resolved); var resolved = _issuesRepository.GetAll().Where(x => x.Status == IssueStatus.Resolved);
var toDelete = resolved.Where(x => x.ResovledDate.HasValue && x.ResovledDate.Value.Date <= now); var toDelete = resolved.Where(x => x.ResovledDate.HasValue && x.ResovledDate.Value.Date >= deletionDate);
foreach (var d in toDelete) foreach (var d in toDelete)
{ {

@ -10,28 +10,23 @@ using Ombi.Schedule.Jobs.Emby;
using Ombi.Schedule.Jobs.Plex.Interfaces; using Ombi.Schedule.Jobs.Plex.Interfaces;
using Ombi.Store.Repository; using Ombi.Store.Repository;
namespace Ombi.Schedule.Jobs.Plex namespace Ombi.Schedule.Jobs.Ombi
{ {
public class MediaDatabaseRefresh : IMediaDatabaseRefresh public class MediaDatabaseRefresh : IMediaDatabaseRefresh
{ {
public MediaDatabaseRefresh(ISettingsService<PlexSettings> s, ILogger<MediaDatabaseRefresh> log, IPlexApi plexApi, public MediaDatabaseRefresh(ISettingsService<PlexSettings> s, ILogger<MediaDatabaseRefresh> log,
IPlexContentRepository plexRepo, IPlexContentSync c, IEmbyContentRepository embyRepo, IEmbyContentSync embySync) IPlexContentRepository plexRepo, IEmbyContentRepository embyRepo, IEmbyContentSync embySync)
{ {
_settings = s; _settings = s;
_log = log; _log = log;
_api = plexApi;
_plexRepo = plexRepo; _plexRepo = plexRepo;
_plexContentSync = c;
_embyRepo = embyRepo; _embyRepo = embyRepo;
_embyContentSync = embySync; _embyContentSync = embySync;
_settings.ClearCache();
} }
private readonly ISettingsService<PlexSettings> _settings; private readonly ISettingsService<PlexSettings> _settings;
private readonly ILogger _log; private readonly ILogger _log;
private readonly IPlexApi _api;
private readonly IPlexContentRepository _plexRepo; private readonly IPlexContentRepository _plexRepo;
private readonly IPlexContentSync _plexContentSync;
private readonly IEmbyContentRepository _embyRepo; private readonly IEmbyContentRepository _embyRepo;
private readonly IEmbyContentSync _embyContentSync; private readonly IEmbyContentSync _embyContentSync;

@ -16,6 +16,7 @@ using Ombi.Api.TheMovieDb;
using Ombi.Api.TheMovieDb.Models; using Ombi.Api.TheMovieDb.Models;
using Ombi.Api.TvMaze; using Ombi.Api.TvMaze;
using Ombi.Core.Settings; using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Notifications; using Ombi.Notifications;
using Ombi.Notifications.Models; using Ombi.Notifications.Models;
@ -36,7 +37,7 @@ namespace Ombi.Schedule.Jobs.Ombi
ISettingsService<EmailNotificationSettings> emailSettings, INotificationTemplatesRepository templateRepo, ISettingsService<EmailNotificationSettings> emailSettings, INotificationTemplatesRepository templateRepo,
UserManager<OmbiUser> um, ISettingsService<NewsletterSettings> newsletter, ILogger<NewsletterJob> log, UserManager<OmbiUser> um, ISettingsService<NewsletterSettings> newsletter, ILogger<NewsletterJob> log,
ILidarrApi lidarrApi, IRepository<LidarrAlbumCache> albumCache, ISettingsService<LidarrSettings> lidarrSettings, ILidarrApi lidarrApi, IRepository<LidarrAlbumCache> albumCache, ISettingsService<LidarrSettings> lidarrSettings,
ISettingsService<OmbiSettings> ombiSettings) ISettingsService<OmbiSettings> ombiSettings, ISettingsService<PlexSettings> plexSettings, ISettingsService<EmbySettings> embySettings)
{ {
_plex = plex; _plex = plex;
_emby = emby; _emby = emby;
@ -49,16 +50,13 @@ namespace Ombi.Schedule.Jobs.Ombi
_emailSettings = emailSettings; _emailSettings = emailSettings;
_newsletterSettings = newsletter; _newsletterSettings = newsletter;
_userManager = um; _userManager = um;
_emailSettings.ClearCache();
_customizationSettings.ClearCache();
_newsletterSettings.ClearCache();
_log = log; _log = log;
_lidarrApi = lidarrApi; _lidarrApi = lidarrApi;
_lidarrAlbumRepository = albumCache; _lidarrAlbumRepository = albumCache;
_lidarrSettings = lidarrSettings; _lidarrSettings = lidarrSettings;
_ombiSettings = ombiSettings; _ombiSettings = ombiSettings;
_ombiSettings.ClearCache(); _plexSettings = plexSettings;
_lidarrSettings.ClearCache(); _embySettings = embySettings;
} }
private readonly IPlexContentRepository _plex; private readonly IPlexContentRepository _plex;
@ -77,6 +75,8 @@ namespace Ombi.Schedule.Jobs.Ombi
private readonly ILidarrApi _lidarrApi; private readonly ILidarrApi _lidarrApi;
private readonly IRepository<LidarrAlbumCache> _lidarrAlbumRepository; private readonly IRepository<LidarrAlbumCache> _lidarrAlbumRepository;
private readonly ISettingsService<LidarrSettings> _lidarrSettings; private readonly ISettingsService<LidarrSettings> _lidarrSettings;
private readonly ISettingsService<PlexSettings> _plexSettings;
private readonly ISettingsService<EmbySettings> _embySettings;
public async Task Start(NewsletterSettings settings, bool test) public async Task Start(NewsletterSettings settings, bool test)
{ {
@ -132,6 +132,8 @@ namespace Ombi.Schedule.Jobs.Ombi
_log.LogInformation("Plex Episodes to send: {0}", plexEpisodesToSend.Count()); _log.LogInformation("Plex Episodes to send: {0}", plexEpisodesToSend.Count());
_log.LogInformation("Emby Episodes to send: {0}", embyEpisodesToSend.Count()); _log.LogInformation("Emby Episodes to send: {0}", embyEpisodesToSend.Count());
var plexSettings = await _plexSettings.GetSettingsAsync();
var embySettings = await _embySettings.GetSettingsAsync();
var body = string.Empty; var body = string.Empty;
if (test) if (test)
{ {
@ -140,11 +142,11 @@ namespace Ombi.Schedule.Jobs.Ombi
var plext = _plex.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10).ToHashSet(); var plext = _plex.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10).ToHashSet();
var embyt = _emby.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); var embyt = _emby.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10).ToHashSet();
var lidarr = lidarrContent.OrderByDescending(x => x.AddedAt).Take(10).ToHashSet(); var lidarr = lidarrContent.OrderByDescending(x => x.AddedAt).Take(10).ToHashSet();
body = await BuildHtml(plexm, embym, plext, embyt, lidarr, settings); body = await BuildHtml(plexm, embym, plext, embyt, lidarr, settings, embySettings, plexSettings);
} }
else else
{ {
body = await BuildHtml(plexContentMoviesToSend, embyContentMoviesToSend, plexEpisodesToSend, embyEpisodesToSend, lidarrContentAlbumsToSend, settings); body = await BuildHtml(plexContentMoviesToSend, embyContentMoviesToSend, plexEpisodesToSend, embyEpisodesToSend, lidarrContentAlbumsToSend, settings, embySettings, plexSettings);
if (body.IsNullOrEmpty()) if (body.IsNullOrEmpty())
{ {
return; return;
@ -333,7 +335,8 @@ namespace Ombi.Schedule.Jobs.Ombi
} }
private async Task<string> BuildHtml(IQueryable<PlexServerContent> plexContentToSend, IQueryable<EmbyContent> embyContentToSend, private async Task<string> BuildHtml(IQueryable<PlexServerContent> plexContentToSend, IQueryable<EmbyContent> embyContentToSend,
HashSet<PlexEpisode> plexEpisodes, HashSet<EmbyEpisode> embyEp, HashSet<LidarrAlbumCache> albums, NewsletterSettings settings) HashSet<PlexEpisode> plexEpisodes, HashSet<EmbyEpisode> embyEp, HashSet<LidarrAlbumCache> albums, NewsletterSettings settings, EmbySettings embySettings,
PlexSettings plexSettings)
{ {
var ombiSettings = await _ombiSettings.GetSettingsAsync(); var ombiSettings = await _ombiSettings.GetSettingsAsync();
var sb = new StringBuilder(); var sb = new StringBuilder();
@ -349,8 +352,16 @@ namespace Ombi.Schedule.Jobs.Ombi
sb.Append("<td style=\"font-family: 'Open Sans', Helvetica, Arial, sans-serif; font-size: 14px; vertical-align: top; \">"); sb.Append("<td style=\"font-family: 'Open Sans', Helvetica, Arial, sans-serif; font-size: 14px; vertical-align: top; \">");
sb.Append("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">"); sb.Append("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">");
sb.Append("<tr>"); sb.Append("<tr>");
await ProcessPlexMovies(plexMovies, sb, ombiSettings.DefaultLanguageCode); if (plexSettings.Enable)
await ProcessEmbyMovies(embyMovies, sb, ombiSettings.DefaultLanguageCode); {
await ProcessPlexMovies(plexMovies, sb, ombiSettings.DefaultLanguageCode);
}
if (embySettings.Enable)
{
await ProcessEmbyMovies(embyMovies, sb, ombiSettings.DefaultLanguageCode);
}
sb.Append("</tr>"); sb.Append("</tr>");
sb.Append("</table>"); sb.Append("</table>");
sb.Append("</td>"); sb.Append("</td>");
@ -367,8 +378,16 @@ namespace Ombi.Schedule.Jobs.Ombi
sb.Append("<td style=\"font-family: 'Open Sans', Helvetica, Arial, sans-serif; font-size: 14px; vertical-align: top; \">"); sb.Append("<td style=\"font-family: 'Open Sans', Helvetica, Arial, sans-serif; font-size: 14px; vertical-align: top; \">");
sb.Append("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">"); sb.Append("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">");
sb.Append("<tr>"); sb.Append("<tr>");
await ProcessPlexTv(plexEpisodes, sb); if (plexSettings.Enable)
await ProcessEmbyTv(embyEp, sb); {
await ProcessPlexTv(plexEpisodes, sb);
}
if (embySettings.Enable)
{
await ProcessEmbyTv(embyEp, sb);
}
sb.Append("</tr>"); sb.Append("</tr>");
sb.Append("</table>"); sb.Append("</table>");
sb.Append("</td>"); sb.Append("</td>");

@ -5,18 +5,13 @@ using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.Http;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire; using Hangfire;
using Hangfire.Console;
using Hangfire.Server; using Hangfire.Server;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Api.Service;
using Ombi.Api.Service.Models;
using Ombi.Core.Processor; using Ombi.Core.Processor;
using Ombi.Core.Settings; using Ombi.Core.Settings;
using Ombi.Helpers; using Ombi.Helpers;
@ -40,7 +35,6 @@ namespace Ombi.Schedule.Jobs.Ombi
Settings = s; Settings = s;
_processProvider = proc; _processProvider = proc;
_appConfig = appConfig; _appConfig = appConfig;
Settings.ClearCache();
} }
private ILogger<OmbiAutomaticUpdater> Logger { get; } private ILogger<OmbiAutomaticUpdater> Logger { get; }

@ -4,6 +4,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire; using Hangfire;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Api.Emby;
using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb;
using Ombi.Api.TheMovieDb.Models; using Ombi.Api.TheMovieDb.Models;
using Ombi.Api.TvMaze; using Ombi.Api.TvMaze;
@ -21,7 +22,8 @@ namespace Ombi.Schedule.Jobs.Ombi
{ {
public RefreshMetadata(IPlexContentRepository plexRepo, IEmbyContentRepository embyRepo, public RefreshMetadata(IPlexContentRepository plexRepo, IEmbyContentRepository embyRepo,
ILogger<RefreshMetadata> log, ITvMazeApi tvApi, ISettingsService<PlexSettings> plexSettings, ILogger<RefreshMetadata> log, ITvMazeApi tvApi, ISettingsService<PlexSettings> plexSettings,
IMovieDbApi movieApi, ISettingsService<EmbySettings> embySettings, IPlexAvailabilityChecker plexAvailability, IEmbyAvaliabilityChecker embyAvaliability) IMovieDbApi movieApi, ISettingsService<EmbySettings> embySettings, IPlexAvailabilityChecker plexAvailability, IEmbyAvaliabilityChecker embyAvaliability,
IEmbyApi embyApi)
{ {
_plexRepo = plexRepo; _plexRepo = plexRepo;
_embyRepo = embyRepo; _embyRepo = embyRepo;
@ -32,6 +34,7 @@ namespace Ombi.Schedule.Jobs.Ombi
_embySettings = embySettings; _embySettings = embySettings;
_plexAvailabilityChecker = plexAvailability; _plexAvailabilityChecker = plexAvailability;
_embyAvaliabilityChecker = embyAvaliability; _embyAvaliabilityChecker = embyAvaliability;
_embyApi = embyApi;
} }
private readonly IPlexContentRepository _plexRepo; private readonly IPlexContentRepository _plexRepo;
@ -43,6 +46,7 @@ namespace Ombi.Schedule.Jobs.Ombi
private readonly ITvMazeApi _tvApi; private readonly ITvMazeApi _tvApi;
private readonly ISettingsService<PlexSettings> _plexSettings; private readonly ISettingsService<PlexSettings> _plexSettings;
private readonly ISettingsService<EmbySettings> _embySettings; private readonly ISettingsService<EmbySettings> _embySettings;
private readonly IEmbyApi _embyApi;
public async Task Start() public async Task Start()
{ {
@ -58,7 +62,7 @@ namespace Ombi.Schedule.Jobs.Ombi
var embySettings = await _embySettings.GetSettingsAsync(); var embySettings = await _embySettings.GetSettingsAsync();
if (embySettings.Enable) if (embySettings.Enable)
{ {
await StartEmby(); await StartEmby(embySettings);
} }
} }
catch (Exception e) catch (Exception e)
@ -123,9 +127,9 @@ namespace Ombi.Schedule.Jobs.Ombi
await StartPlexTv(allTv); await StartPlexTv(allTv);
} }
private async Task StartEmby() private async Task StartEmby(EmbySettings s)
{ {
await StartEmbyMovies(); await StartEmbyMovies(s);
await StartEmbyTv(); await StartEmbyTv();
} }
@ -158,7 +162,7 @@ namespace Ombi.Schedule.Jobs.Ombi
_plexRepo.UpdateWithoutSave(show); _plexRepo.UpdateWithoutSave(show);
} }
tvCount++; tvCount++;
if (tvCount >= 20) if (tvCount >= 75)
{ {
await _plexRepo.SaveChangesAsync(); await _plexRepo.SaveChangesAsync();
tvCount = 0; tvCount = 0;
@ -198,7 +202,7 @@ namespace Ombi.Schedule.Jobs.Ombi
_embyRepo.UpdateWithoutSave(show); _embyRepo.UpdateWithoutSave(show);
} }
tvCount++; tvCount++;
if (tvCount >= 20) if (tvCount >= 75)
{ {
await _embyRepo.SaveChangesAsync(); await _embyRepo.SaveChangesAsync();
tvCount = 0; tvCount = 0;
@ -229,7 +233,7 @@ namespace Ombi.Schedule.Jobs.Ombi
_plexRepo.UpdateWithoutSave(movie); _plexRepo.UpdateWithoutSave(movie);
} }
movieCount++; movieCount++;
if (movieCount >= 20) if (movieCount >= 75)
{ {
await _plexRepo.SaveChangesAsync(); await _plexRepo.SaveChangesAsync();
movieCount = 0; movieCount = 0;
@ -239,31 +243,56 @@ namespace Ombi.Schedule.Jobs.Ombi
await _plexRepo.SaveChangesAsync(); await _plexRepo.SaveChangesAsync();
} }
private async Task StartEmbyMovies() private async Task StartEmbyMovies(EmbySettings settings)
{ {
var allMovies = _embyRepo.GetAll().Where(x => var allMovies = _embyRepo.GetAll().Where(x =>
x.Type == EmbyMediaType.Movie && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue())); x.Type == EmbyMediaType.Movie && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue()));
int movieCount = 0; int movieCount = 0;
foreach (var movie in allMovies) foreach (var movie in allMovies)
{ {
var hasImdb = movie.ImdbId.HasValue(); movie.ImdbId.HasValue();
var hasTheMovieDb = movie.TheMovieDbId.HasValue(); movie.TheMovieDbId.HasValue();
// Movies don't really use TheTvDb // Movies don't really use TheTvDb
if (!hasImdb) // Check if it even has 1 ID
if (!movie.HasImdb && !movie.HasTheMovieDb)
{ {
var imdbId = await GetImdbId(hasTheMovieDb, false, movie.Title, movie.TheMovieDbId, string.Empty); // Ok this sucks,
// The only think I can think that has happened is that we scanned Emby before Emby has got the metadata
// So let's recheck emby to see if they have got the metadata now
_log.LogInformation($"Movie {movie.Title} does not have a ImdbId or TheMovieDbId, so rechecking emby");
foreach (var server in settings.Servers)
{
_log.LogInformation($"Checking server {server.Name} for upto date metadata");
var movieInfo = await _embyApi.GetMovieInformation(movie.EmbyId, server.ApiKey, server.AdministratorId,
server.FullUri);
if (movieInfo.ProviderIds?.Imdb.HasValue() ?? false)
{
movie.ImdbId = movieInfo.ProviderIds.Imdb;
}
if (movieInfo.ProviderIds?.Tmdb.HasValue() ?? false)
{
movie.TheMovieDbId = movieInfo.ProviderIds.Tmdb;
}
}
}
if (!movie.HasImdb)
{
var imdbId = await GetImdbId(movie.HasTheMovieDb, false, movie.Title, movie.TheMovieDbId, string.Empty);
movie.ImdbId = imdbId; movie.ImdbId = imdbId;
_embyRepo.UpdateWithoutSave(movie); _embyRepo.UpdateWithoutSave(movie);
} }
if (!hasTheMovieDb) if (!movie.HasTheMovieDb)
{ {
var id = await GetTheMovieDbId(false, hasImdb, string.Empty, movie.ImdbId, movie.Title, true); var id = await GetTheMovieDbId(false, movie.HasImdb, string.Empty, movie.ImdbId, movie.Title, true);
movie.TheMovieDbId = id; movie.TheMovieDbId = id;
_embyRepo.UpdateWithoutSave(movie); _embyRepo.UpdateWithoutSave(movie);
} }
movieCount++; movieCount++;
if (movieCount >= 20) if (movieCount >= 75)
{ {
await _embyRepo.SaveChangesAsync(); await _embyRepo.SaveChangesAsync();
movieCount = 0; movieCount = 0;

@ -20,8 +20,6 @@ namespace Ombi.Schedule.Jobs.Ombi
_email = provider; _email = provider;
_templates = template; _templates = template;
_customizationSettings = c; _customizationSettings = c;
email.ClearCache();
_customizationSettings.ClearCache();
} }
private readonly ISettingsService<EmailNotificationSettings> _emailSettings; private readonly ISettingsService<EmailNotificationSettings> _emailSettings;

@ -57,7 +57,6 @@ namespace Ombi.Schedule.Jobs.Plex
EpisodeSync = epsiodeSync; EpisodeSync = epsiodeSync;
Metadata = metadataRefresh; Metadata = metadataRefresh;
Checker = checker; Checker = checker;
plex.ClearCache();
} }
private ISettingsService<PlexSettings> Plex { get; } private ISettingsService<PlexSettings> Plex { get; }

@ -26,7 +26,6 @@ namespace Ombi.Schedule.Jobs.Plex
_api = plexApi; _api = plexApi;
_repo = repo; _repo = repo;
_availabilityChecker = a; _availabilityChecker = a;
_settings.ClearCache();
} }
private readonly ISettingsService<PlexSettings> _settings; private readonly ISettingsService<PlexSettings> _settings;

@ -24,8 +24,6 @@ namespace Ombi.Schedule.Jobs.Plex
_log = log; _log = log;
_plexSettings = plexSettings; _plexSettings = plexSettings;
_userManagementSettings = ums; _userManagementSettings = ums;
_userManagementSettings.ClearCache();
_plexSettings.ClearCache();
} }
private readonly IPlexApi _api; private readonly IPlexApi _api;

@ -22,7 +22,6 @@ namespace Ombi.Schedule.Jobs.Radarr
RadarrApi = radarrApi; RadarrApi = radarrApi;
Logger = log; Logger = log;
_ctx = ctx; _ctx = ctx;
RadarrSettings.ClearCache();
} }
private ISettingsService<RadarrSettings> RadarrSettings { get; } private ISettingsService<RadarrSettings> RadarrSettings { get; }

@ -22,7 +22,6 @@ namespace Ombi.Schedule.Jobs.SickRage
_api = api; _api = api;
_log = l; _log = l;
_ctx = ctx; _ctx = ctx;
_settings.ClearCache();
} }
private readonly ISettingsService<SickRageSettings> _settings; private readonly ISettingsService<SickRageSettings> _settings;

@ -25,7 +25,6 @@ namespace Ombi.Schedule.Jobs.Sonarr
_api = api; _api = api;
_log = l; _log = l;
_ctx = ctx; _ctx = ctx;
_settings.ClearCache();
} }
private readonly ISettingsService<SonarrSettings> _settings; private readonly ISettingsService<SonarrSettings> _settings;

@ -61,7 +61,7 @@ namespace Ombi.Settings.Settings
var model = obj; var model = obj;
return model; return model;
}, DateTime.Now.AddHours(2)); }, DateTime.Now.AddHours(5));
} }
public bool SaveSettings(T model) public bool SaveSettings(T model)

@ -87,53 +87,6 @@ namespace Ombi.Store.Context
public void Seed() public void Seed()
{ {
// VACUUM;
Database.ExecuteSqlCommand("VACUUM;");
// Make sure we have the roles
var newsletterRole = Roles.Where(x => x.Name == OmbiRoles.ReceivesNewsletter);
if (!newsletterRole.Any())
{
Roles.Add(new IdentityRole(OmbiRoles.ReceivesNewsletter)
{
NormalizedName = OmbiRoles.ReceivesNewsletter.ToUpper()
});
SaveChanges();
}
var requestMusicRole = Roles.Where(x => x.Name == OmbiRoles.RequestMusic);
if (!requestMusicRole.Any())
{
Roles.Add(new IdentityRole(OmbiRoles.RequestMusic)
{
NormalizedName = OmbiRoles.RequestMusic.ToUpper()
});
Roles.Add(new IdentityRole(OmbiRoles.AutoApproveMusic)
{
NormalizedName = OmbiRoles.AutoApproveMusic.ToUpper()
});
SaveChanges();
}
var manageOwnRequestsRole = Roles.Where(x => x.Name == OmbiRoles.ManageOwnRequests);
if (!manageOwnRequestsRole.Any())
{
Roles.Add(new IdentityRole(OmbiRoles.ManageOwnRequests)
{
NormalizedName = OmbiRoles.ManageOwnRequests.ToUpper()
});
SaveChanges();
}
var editCustomPage = Roles.Where(x => x.Name == OmbiRoles.EditCustomPage);
if (!editCustomPage.Any())
{
Roles.Add(new IdentityRole(OmbiRoles.EditCustomPage)
{
NormalizedName = OmbiRoles.EditCustomPage.ToUpper()
});
SaveChanges();
}
// Make sure we have the API User // Make sure we have the API User
var apiUserExists = Users.Any(x => x.UserName.Equals("Api", StringComparison.CurrentCultureIgnoreCase)); var apiUserExists = Users.Any(x => x.UserName.Equals("Api", StringComparison.CurrentCultureIgnoreCase));
if (!apiUserExists) if (!apiUserExists)

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Globalization;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
@ -27,9 +28,10 @@ namespace Ombi.Store.Repository.Requests
public bool Approved { get; set; } public bool Approved { get; set; }
public bool Requested { get; set; } public bool Requested { get; set; }
public int SeasonId { get; set; } public int SeasonId { get; set; }
[ForeignKey(nameof(SeasonId))] [ForeignKey(nameof(SeasonId))]
public SeasonRequests Season { get; set; } public SeasonRequests Season { get; set; }
[NotMapped] public string AirDateDisplay => AirDate == DateTime.MinValue ? "Unknown" : AirDate.ToString(CultureInfo.InvariantCulture);
} }
} }

@ -17,10 +17,6 @@ namespace Ombi.Store.Entities.Requests
public DateTime ReleaseDate { get; set; } public DateTime ReleaseDate { get; set; }
public string Status { get; set; } public string Status { get; set; }
/// <summary>
/// This is so we can correctly send the right amount of seasons to Sonarr
/// </summary>
[NotMapped]
public int TotalSeasons { get; set; } public int TotalSeasons { get; set; }
public List<ChildRequests> ChildRequests { get; set; } public List<ChildRequests> ChildRequests { get; set; }

File diff suppressed because it is too large Load Diff

@ -0,0 +1,32 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Ombi.Helpers;
namespace Ombi.Store.Migrations
{
public partial class Roles : Migration
{
protected override void Up(MigrationBuilder mb)
{
// Make sure we have the roles
InsertRole(mb, OmbiRoles.ReceivesNewsletter);
InsertRole(mb, OmbiRoles.RequestMusic);
InsertRole(mb, OmbiRoles.AutoApproveMusic);
InsertRole(mb, OmbiRoles.ManageOwnRequests);
InsertRole(mb, OmbiRoles.EditCustomPage);
}
private void InsertRole(MigrationBuilder mb, string role)
{
mb.Sql($@"
INSERT INTO AspnetRoles(Id, ConcurrencyStamp, Name, NormalizedName)
SELECT '{Guid.NewGuid().ToString()}','{Guid.NewGuid().ToString()}','{role}', '{role.ToUpper()}'
WHERE NOT EXISTS(SELECT 1 FROM AspnetRoles WHERE Name = '{role}');");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,23 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Ombi.Store.Migrations
{
public partial class TvRequestsTotalSeasons : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "TotalSeasons",
table: "TvRequests",
nullable: false,
defaultValue: 0);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "TotalSeasons",
table: "TvRequests");
}
}
}

@ -819,6 +819,8 @@ namespace Ombi.Store.Migrations
b.Property<string>("Title"); b.Property<string>("Title");
b.Property<int>("TotalSeasons");
b.Property<int>("TvDbId"); b.Property<int>("TvDbId");
b.HasKey("Id"); b.HasKey("Id");

@ -146,6 +146,7 @@ export interface IEpisodesRequests {
episodeNumber: number; episodeNumber: number;
title: string; title: string;
airDate: Date; airDate: Date;
airDateDisplay: string;
url: string; url: string;
available: boolean; available: boolean;
requested: boolean; requested: boolean;

@ -42,9 +42,12 @@
<td> <td>
{{ep.title}} {{ep.title}}
</td> </td>
<td> <td *ngIf="ep.airDateDisplay != 'Unknown'">
{{ep.airDate | amLocal | amDateFormat: 'L' }} {{ep.airDate | amLocal | amDateFormat: 'L' }}
</td> </td>
<td *ngIf="ep.airDateDisplay == 'Unknown'">
{{ep.airDateDisplay }}
</td>
<td> <td>
<ng-template [ngIf]="ep.available"><span class="label label-success" id="availableLabel">Available</span></ng-template> <ng-template [ngIf]="ep.available"><span class="label label-success" id="availableLabel">Available</span></ng-template>
<ng-template [ngIf]="ep.approved && !ep.available "><span class="label label-info" id="processingRequestLabel">Processing Request</span></ng-template> <ng-template [ngIf]="ep.approved && !ep.available "><span class="label label-info" id="processingRequestLabel">Processing Request</span></ng-template>

@ -15,4 +15,8 @@ export class MobileService extends ServiceHelpers {
public getUserDeviceList(): Observable<IMobileUsersViewModel[]> { public getUserDeviceList(): Observable<IMobileUsersViewModel[]> {
return this.http.get<IMobileUsersViewModel[]>(`${this.url}notification/`, {headers: this.headers}); return this.http.get<IMobileUsersViewModel[]>(`${this.url}notification/`, {headers: this.headers});
} }
public deleteUser(userId: string): Observable<boolean> {
return this.http.post<boolean>(`${this.url}remove/`, userId, {headers: this.headers});
}
} }

@ -38,7 +38,7 @@
<span>Discord</span> <span>Discord</span>
</td> </td>
<td> <td>
<a href="https://discord.gg/Sa7wNWb" target="_blank">https://discord.gg/</a> <a href="https://discord.gg/Sa7wNWb" target="_blank">https://discord.gg/Sa7wNWb</a>
</td> </td>
</tr> </tr>

@ -35,7 +35,7 @@
<div class="row"> <div class="row">
<div class="form-group"> <div class="form-group">
<label for="select" class="control-label">User to send test notification to</label> <label for="select" class="control-label">Users</label>
<div> <div>
<select class="form-control form-control-custom" id="select" [(ngModel)]="testUserId" [ngModelOptions]="{standalone: true}"> <select class="form-control form-control-custom" id="select" [(ngModel)]="testUserId" [ngModelOptions]="{standalone: true}">
<option value="">Please select</option> <option value="">Please select</option>
@ -46,7 +46,12 @@
<div class="form-group"> <div class="form-group">
<div> <div>
<button [disabled]="form.invalid" type="button" (click)="test(form)" class="btn btn-danger-outline">Test</button> <button [disabled]="form.invalid" type="button" (click)="test(form)" class="btn btn-danger-outline">Send Test Notification</button>
</div>
</div>
<div class="form-group">
<div>
<button [disabled]="form.invalid" type="button" (click)="remove(form)" class="btn btn-danger-outline">Remove User</button>
</div> </div>
</div> </div>

@ -79,4 +79,24 @@ export class MobileComponent implements OnInit {
}); });
} }
public remove() {
if (!this.testUserId) {
this.notificationService.warning("Warning", "Please select a user to remove");
return;
}
this.mobileService.deleteUser(this.testUserId).subscribe(x => {
if (x) {
this.notificationService.success("Removed users notification");
const userToRemove = this.userList.filter(u => {
return u.userId === this.testUserId;
})[1];
this.userList.splice(this.userList.indexOf(userToRemove),1);
} else {
this.notificationService.error("There was an error when removing the notification. Please check your logs");
}
});
}
} }

@ -22,7 +22,6 @@ namespace Ombi.Controllers.V1.External
RadarrApi = radarr; RadarrApi = radarr;
RadarrSettings = settings; RadarrSettings = settings;
Cache = mem; Cache = mem;
RadarrSettings.ClearCache();
} }
private IRadarrApi RadarrApi { get; } private IRadarrApi RadarrApi { get; }

@ -21,7 +21,6 @@ namespace Ombi.Controllers.V1.External
SonarrApi = sonarr; SonarrApi = sonarr;
SonarrV3Api = sonarrv3; SonarrV3Api = sonarrv3;
SonarrSettings = settings; SonarrSettings = settings;
SonarrSettings.ClearCache();
} }
private ISonarrApi SonarrApi { get; } private ISonarrApi SonarrApi { get; }

@ -130,7 +130,7 @@ namespace Ombi.Controllers.V1
public async Task<int> CreateIssue([FromBody]Issues i) public async Task<int> CreateIssue([FromBody]Issues i)
{ {
i.IssueCategory = null; i.IssueCategory = null;
i.UserReportedId = (await _userManager.Users.FirstOrDefaultAsync(x => x.UserName == User.Identity.Name)).Id; i.UserReportedId = (await _userManager.Users.FirstOrDefaultAsync(x => x.UserName.Equals(User.Identity.Name, StringComparison.InvariantCultureIgnoreCase))).Id;
await _issues.Add(i); await _issues.Add(i);
var category = await _categories.GetAll().FirstOrDefaultAsync(x => i.IssueCategoryId == x.Id); var category = await _categories.GetAll().FirstOrDefaultAsync(x => i.IssueCategoryId == x.Id);
if (category != null) if (category != null)
@ -197,7 +197,7 @@ namespace Ombi.Controllers.V1
[HttpPost("comments")] [HttpPost("comments")]
public async Task<IssueComments> AddComment([FromBody] NewIssueCommentViewModel comment) public async Task<IssueComments> AddComment([FromBody] NewIssueCommentViewModel comment)
{ {
var user = await _userManager.Users.Where(x => User.Identity.Name == x.UserName) var user = await _userManager.Users.Where(x => User.Identity.Name.Equals(x.UserName, StringComparison.InvariantCultureIgnoreCase))
.FirstOrDefaultAsync(); .FirstOrDefaultAsync();
var issue = await _issues.GetAll().Include(x => x.UserReported).Include(x => x.IssueCategory).FirstOrDefaultAsync(x => x.Id == comment.IssueId); var issue = await _issues.GetAll().Include(x => x.UserReported).Include(x => x.IssueCategory).FirstOrDefaultAsync(x => x.Id == comment.IssueId);
if (issue == null) if (issue == null)
@ -256,7 +256,7 @@ namespace Ombi.Controllers.V1
[HttpPost("status")] [HttpPost("status")]
public async Task<bool> UpdateStatus([FromBody] IssueStateViewModel model) public async Task<bool> UpdateStatus([FromBody] IssueStateViewModel model)
{ {
var user = await _userManager.Users.Where(x => User.Identity.Name == x.UserName) var user = await _userManager.Users.Where(x => User.Identity.Name.Equals(x.UserName, StringComparison.InvariantCultureIgnoreCase))
.FirstOrDefaultAsync(); .FirstOrDefaultAsync();
var issue = await _issues.GetAll().Include(x => x.UserReported).Include(x => x.IssueCategory).FirstOrDefaultAsync(x => x.Id == model.IssueId); var issue = await _issues.GetAll().Include(x => x.UserReported).Include(x => x.IssueCategory).FirstOrDefaultAsync(x => x.Id == model.IssueId);
if (issue == null) if (issue == null)
@ -265,6 +265,11 @@ namespace Ombi.Controllers.V1
} }
issue.Status = model.Status; issue.Status = model.Status;
if (model.Status == IssueStatus.Resolved)
{
issue.ResovledDate = DateTime.UtcNow;
}
await _issues.SaveChangesAsync(); await _issues.SaveChangesAsync();
if (issue.Status == IssueStatus.Resolved) if (issue.Status == IssueStatus.Resolved)

@ -5,6 +5,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Ombi.Attributes; using Ombi.Attributes;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Helpers; using Ombi.Helpers;
@ -20,14 +21,16 @@ namespace Ombi.Controllers.V1
[ApiController] [ApiController]
public class MobileController : ControllerBase public class MobileController : ControllerBase
{ {
public MobileController(IRepository<NotificationUserId> notification, OmbiUserManager user) public MobileController(IRepository<NotificationUserId> notification, OmbiUserManager user, ILogger<MobileController> log)
{ {
_notification = notification; _notification = notification;
_userManager = user; _userManager = user;
_log = log;
} }
private readonly IRepository<NotificationUserId> _notification; private readonly IRepository<NotificationUserId> _notification;
private readonly OmbiUserManager _userManager; private readonly OmbiUserManager _userManager;
private readonly ILogger _log;
[HttpPost("Notification")] [HttpPost("Notification")]
[ApiExplorerSettings(IgnoreApi = true)] [ApiExplorerSettings(IgnoreApi = true)]
@ -78,5 +81,24 @@ namespace Ombi.Controllers.V1
} }
return vm; return vm;
} }
[HttpPost]
[ApiExplorerSettings(IgnoreApi = true)]
[Admin]
public async Task<bool> RemoveUser([FromBody] string userId)
{
var user = await _userManager.Users.Include(x => x.NotificationUserIds).FirstOrDefaultAsync(x => x.Id.Equals(userId, StringComparison.InvariantCultureIgnoreCase));
try
{
await _notification.DeleteRange(user.NotificationUserIds);
return true;
}
catch (Exception e)
{
_log.LogError(e, "Could not delete user notification");
}
return false;
}
} }
} }

@ -4190,7 +4190,8 @@
}, },
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true "bundled": true,
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@ -4208,11 +4209,13 @@
}, },
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true "bundled": true,
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -4225,15 +4228,18 @@
}, },
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true "bundled": true,
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true "bundled": true,
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true "bundled": true,
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@ -4336,7 +4342,8 @@
}, },
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"bundled": true "bundled": true,
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@ -4346,6 +4353,7 @@
"is-fullwidth-code-point": { "is-fullwidth-code-point": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@ -4358,17 +4366,20 @@
"minimatch": { "minimatch": {
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
}, },
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true "bundled": true,
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.3.5", "version": "2.3.5",
"bundled": true, "bundled": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.2", "safe-buffer": "^5.1.2",
"yallist": "^3.0.0" "yallist": "^3.0.0"
@ -4385,6 +4396,7 @@
"mkdirp": { "mkdirp": {
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
@ -4457,7 +4469,8 @@
}, },
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true "bundled": true,
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
@ -4467,6 +4480,7 @@
"once": { "once": {
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@ -4542,7 +4556,8 @@
}, },
"safe-buffer": { "safe-buffer": {
"version": "5.1.2", "version": "5.1.2",
"bundled": true "bundled": true,
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
@ -4572,6 +4587,7 @@
"string-width": { "string-width": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@ -4589,6 +4605,7 @@
"strip-ansi": { "strip-ansi": {
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@ -4627,11 +4644,13 @@
}, },
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true "bundled": true,
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.0.3", "version": "3.0.3",
"bundled": true "bundled": true,
"optional": true
} }
} }
}, },

@ -126,7 +126,7 @@
"GridTitle": "Título", "GridTitle": "Título",
"AirDate": "Fecha de estreno", "AirDate": "Fecha de estreno",
"GridStatus": "Estado", "GridStatus": "Estado",
"ReportIssue": "Informar de un problema/error", "ReportIssue": "Informar de Problema",
"Filter": "Filtrar", "Filter": "Filtrar",
"Sort": "Ordenar", "Sort": "Ordenar",
"SeasonNumberHeading": "Temporada: {seasonNumber}", "SeasonNumberHeading": "Temporada: {seasonNumber}",

@ -13,7 +13,7 @@
"ContinueButton": "Doorgaan", "ContinueButton": "Doorgaan",
"Available": "Beschikbaar", "Available": "Beschikbaar",
"PartiallyAvailable": "Deels Beschikbaar", "PartiallyAvailable": "Deels Beschikbaar",
"Monitored": "Gecontroleerd", "Monitored": "Onder toezicht",
"NotAvailable": "Niet Beschikbaar", "NotAvailable": "Niet Beschikbaar",
"ProcessingRequest": "Verzoek wordt verwerkt", "ProcessingRequest": "Verzoek wordt verwerkt",
"PendingApproval": "Wacht op goedkeuring", "PendingApproval": "Wacht op goedkeuring",

@ -48,7 +48,7 @@
"Requests": "Solicitações", "Requests": "Solicitações",
"UserManagement": "Gerenciador de Usuário", "UserManagement": "Gerenciador de Usuário",
"Issues": "Problemas", "Issues": "Problemas",
"Vote": "Vote", "Vote": "Votar",
"Donate": "Fazer uma doação!", "Donate": "Fazer uma doação!",
"DonateLibraryMaintainer": "Doar para o Dono da Biblioteca", "DonateLibraryMaintainer": "Doar para o Dono da Biblioteca",
"DonateTooltip": "É assim que eu convenço a minha mulher a deixar-me passar o meu tempo livre desenvolvendo Ombi;)", "DonateTooltip": "É assim que eu convenço a minha mulher a deixar-me passar o meu tempo livre desenvolvendo Ombi;)",
@ -74,7 +74,7 @@
"ViewOnEmby": "Assistir no Emby", "ViewOnEmby": "Assistir no Emby",
"RequestAdded": "Pedido de {{title}} foi adicionado com sucesso", "RequestAdded": "Pedido de {{title}} foi adicionado com sucesso",
"Similar": "Semelhante", "Similar": "Semelhante",
"Refine": "Refine", "Refine": "Filtro",
"Movies": { "Movies": {
"PopularMovies": "Filmes populares", "PopularMovies": "Filmes populares",
"UpcomingMovies": "Próximos filmes", "UpcomingMovies": "Próximos filmes",
@ -137,11 +137,11 @@
"SortStatusAsc": "Status ▲", "SortStatusAsc": "Status ▲",
"SortStatusDesc": "Status ▼", "SortStatusDesc": "Status ▼",
"Remaining": { "Remaining": {
"Quota": "{{remaining}}/{{total}} requests remaining", "Quota": "{{remaining}}/{{total}} solicitações restantes",
"NextDays": "Another request will be added in {{time}} days", "NextDays": "Outro pedido será adicionado em {{time}} dias",
"NextHours": "Another request will be added in {{time}} hours", "NextHours": "Outro pedido será adicionado em {{time}} horas",
"NextMinutes": "Another request will be added in {{time}} minutes", "NextMinutes": "Outro pedido será adicionado em {{time}} minutos",
"NextMinute": "Another request will be added in {{time}} minute" "NextMinute": "Outro pedido será adicionado em {{time}} minuto"
} }
}, },
"Issues": { "Issues": {
@ -171,15 +171,15 @@
"PendingApproval": "Aprovação Pendente" "PendingApproval": "Aprovação Pendente"
}, },
"UserManagment": { "UserManagment": {
"TvRemaining": "TV: {{remaining}}/{{total}} remaining", "TvRemaining": "Tv: {{remaining}}/{{total}} restantes",
"MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", "MovieRemaining": "Filmes: {{remaining}}/{{total}} restantes",
"MusicRemaining": "Music: {{remaining}}/{{total}} remaining", "MusicRemaining": "Música: {{remaining}}/{{total}} restantes",
"TvDue": "TV: {{date}}", "TvDue": "TV: {{date}}",
"MovieDue": "Movie: {{date}}", "MovieDue": "Filme: {{date}}",
"MusicDue": "Music: {{date}}" "MusicDue": "Música: {{date}}"
}, },
"Votes": { "Votes": {
"CompletedVotesTab": "Voted", "CompletedVotesTab": "Votado",
"VotesTab": "Votes Needed" "VotesTab": "Votos necessários"
} }
} }

Loading…
Cancel
Save