mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-19 04:49:33 -07:00
Merge branch 'develop' into newsletterenhancement
This commit is contained in:
commit
fcdabb8c2a
30 changed files with 206 additions and 3674 deletions
3659
CHANGELOG.md
3659
CHANGELOG.md
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
#tool "nuget:?package=GitVersion.CommandLine"
|
#tool "nuget:?package=GitVersion.CommandLine"
|
||||||
#addin "Cake.Gulp"
|
#addin "Cake.Gulp"
|
||||||
#addin "Cake.Npm"
|
#addin "nuget:?package=Cake.Npm&version=0.13.0"
|
||||||
#addin "SharpZipLib"
|
#addin "SharpZipLib"
|
||||||
#addin nuget:?package=Cake.Compression&version=0.1.4
|
#addin nuget:?package=Cake.Compression&version=0.1.4
|
||||||
#addin "Cake.Incubator"
|
#addin "Cake.Incubator"
|
||||||
|
|
|
@ -55,15 +55,24 @@ namespace Ombi.Core.Authentication
|
||||||
return await _api.GetAccount(accessToken);
|
return await _api.GetAccount(accessToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Uri> GetOAuthUrl(int pinId, string code)
|
public async Task<Uri> GetOAuthUrl(int pinId, string code, string websiteAddress = null)
|
||||||
{
|
{
|
||||||
var settings = await _customizationSettingsService.GetSettingsAsync();
|
Uri url;
|
||||||
if (settings.ApplicationUrl.IsNullOrEmpty())
|
if (websiteAddress.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
return null;
|
var settings = await _customizationSettingsService.GetSettingsAsync();
|
||||||
|
if (settings.ApplicationUrl.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
url = _api.GetOAuthUrl(pinId, code, settings.ApplicationUrl, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
url = _api.GetOAuthUrl(pinId, code, websiteAddress, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = _api.GetOAuthUrl(pinId, code, settings.ApplicationUrl, false);
|
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,5 +18,6 @@ namespace Ombi.Core.Engine.Interfaces
|
||||||
Task<RequestEngineResult> ApproveMovieById(int requestId);
|
Task<RequestEngineResult> ApproveMovieById(int requestId);
|
||||||
Task<RequestEngineResult> DenyMovieById(int modelId);
|
Task<RequestEngineResult> DenyMovieById(int modelId);
|
||||||
Task<IEnumerable<MovieRequests>> Filter(FilterViewModel vm);
|
Task<IEnumerable<MovieRequests>> Filter(FilterViewModel vm);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,5 +17,6 @@ namespace Ombi.Core.Engine.Interfaces
|
||||||
|
|
||||||
Task<RequestEngineResult> MarkUnavailable(int modelId);
|
Task<RequestEngineResult> MarkUnavailable(int modelId);
|
||||||
Task<RequestEngineResult> MarkAvailable(int modelId);
|
Task<RequestEngineResult> MarkAvailable(int modelId);
|
||||||
|
Task<int> GetTotal();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -144,6 +144,19 @@ namespace Ombi.Core.Engine
|
||||||
return allRequests;
|
return allRequests;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<int> GetTotal()
|
||||||
|
{
|
||||||
|
var shouldHide = await HideFromOtherUsers();
|
||||||
|
if (shouldHide.Hide)
|
||||||
|
{
|
||||||
|
return await MovieRepository.GetWithUser(shouldHide.UserId).CountAsync();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return await MovieRepository.GetWithUser().CountAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the requests.
|
/// Gets the requests.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -130,7 +130,7 @@ namespace Ombi.Core.Engine
|
||||||
var newRequest = tvBuilder.CreateNewRequest(tv);
|
var newRequest = tvBuilder.CreateNewRequest(tv);
|
||||||
return await AddRequest(newRequest.NewRequest);
|
return await AddRequest(newRequest.NewRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<TvRequests>> GetRequests(int count, int position)
|
public async Task<IEnumerable<TvRequests>> GetRequests(int count, int position)
|
||||||
{
|
{
|
||||||
var shouldHide = await HideFromOtherUsers();
|
var shouldHide = await HideFromOtherUsers();
|
||||||
|
@ -280,7 +280,7 @@ namespace Ombi.Core.Engine
|
||||||
results.Background = PosterPathHelper.FixBackgroundPath(request.Background);
|
results.Background = PosterPathHelper.FixBackgroundPath(request.Background);
|
||||||
results.QualityOverride = request.QualityOverride;
|
results.QualityOverride = request.QualityOverride;
|
||||||
results.RootFolder = request.RootFolder;
|
results.RootFolder = request.RootFolder;
|
||||||
|
|
||||||
await TvRepository.Update(results);
|
await TvRepository.Update(results);
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
@ -432,6 +432,19 @@ namespace Ombi.Core.Engine
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<int> GetTotal()
|
||||||
|
{
|
||||||
|
var shouldHide = await HideFromOtherUsers();
|
||||||
|
if (shouldHide.Hide)
|
||||||
|
{
|
||||||
|
return await TvRepository.Get(shouldHide.UserId).CountAsync();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return await TvRepository.Get().CountAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<RequestEngineResult> AddExistingRequest(ChildRequests newRequest, TvRequests existingRequest)
|
private async Task<RequestEngineResult> AddExistingRequest(ChildRequests newRequest, TvRequests existingRequest)
|
||||||
{
|
{
|
||||||
// Add the child
|
// Add the child
|
||||||
|
|
|
@ -9,7 +9,7 @@ namespace Ombi.Core.Authentication
|
||||||
{
|
{
|
||||||
Task<string> GetAccessTokenFromPin(int pinId);
|
Task<string> GetAccessTokenFromPin(int pinId);
|
||||||
Task<OAuthPin> RequestPin();
|
Task<OAuthPin> RequestPin();
|
||||||
Task<Uri> GetOAuthUrl(int pinId, string code);
|
Task<Uri> GetOAuthUrl(int pinId, string code, string websiteAddress = null);
|
||||||
Uri GetWizardOAuthUrl(int pinId, string code, string websiteAddress);
|
Uri GetWizardOAuthUrl(int pinId, string code, string websiteAddress);
|
||||||
Task<PlexAccount> GetAccount(string accessToken);
|
Task<PlexAccount> GetAccount(string accessToken);
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,5 +65,15 @@ namespace Ombi.Helpers
|
||||||
securePassword.MakeReadOnly();
|
securePassword.MakeReadOnly();
|
||||||
return securePassword;
|
return securePassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int IntParseLinq(string stringIn)
|
||||||
|
{
|
||||||
|
if (int.TryParse(stringIn, out var result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -112,6 +112,7 @@ namespace Ombi.Helpers
|
||||||
|
|
||||||
return uriBuilder.Uri;
|
return uriBuilder.Uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ApplicationSettingsException : Exception
|
public class ApplicationSettingsException : Exception
|
||||||
|
|
|
@ -99,8 +99,8 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Episode);
|
addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Episode);
|
||||||
|
|
||||||
// Filter out the ones that we haven't sent yet
|
// Filter out the ones that we haven't sent yet
|
||||||
var plexContentMoviesToSend = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !addedPlexMovieLogIds.Contains(int.Parse(x.TheMovieDbId)));
|
var plexContentMoviesToSend = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !addedPlexMovieLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId)));
|
||||||
var embyContentMoviesToSend = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !addedEmbyMoviesLogIds.Contains(int.Parse(x.TheMovieDbId)));
|
var embyContentMoviesToSend = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !addedEmbyMoviesLogIds.Contains(StringHelper.IntParseLinq(x.TheMovieDbId)));
|
||||||
_log.LogInformation("Plex Movies to send: {0}", plexContentMoviesToSend.Count());
|
_log.LogInformation("Plex Movies to send: {0}", plexContentMoviesToSend.Count());
|
||||||
_log.LogInformation("Emby Movies to send: {0}", embyContentMoviesToSend.Count());
|
_log.LogInformation("Emby Movies to send: {0}", embyContentMoviesToSend.Count());
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
AddedAt = DateTime.Now,
|
AddedAt = DateTime.Now,
|
||||||
Type = RecentlyAddedType.Plex,
|
Type = RecentlyAddedType.Plex,
|
||||||
ContentType = ContentType.Parent,
|
ContentType = ContentType.Parent,
|
||||||
ContentId = int.Parse(p.TheMovieDbId),
|
ContentId = StringHelper.IntParseLinq(p.TheMovieDbId),
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
AddedAt = DateTime.Now,
|
AddedAt = DateTime.Now,
|
||||||
Type = RecentlyAddedType.Plex,
|
Type = RecentlyAddedType.Plex,
|
||||||
ContentType = ContentType.Episode,
|
ContentType = ContentType.Episode,
|
||||||
ContentId = int.Parse(p.Series.TvDbId),
|
ContentId = StringHelper.IntParseLinq(p.Series.TvDbId),
|
||||||
EpisodeNumber = p.EpisodeNumber,
|
EpisodeNumber = p.EpisodeNumber,
|
||||||
SeasonNumber = p.SeasonNumber
|
SeasonNumber = p.SeasonNumber
|
||||||
});
|
});
|
||||||
|
@ -200,7 +200,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
AddedAt = DateTime.Now,
|
AddedAt = DateTime.Now,
|
||||||
Type = RecentlyAddedType.Emby,
|
Type = RecentlyAddedType.Emby,
|
||||||
ContentType = ContentType.Parent,
|
ContentType = ContentType.Parent,
|
||||||
ContentId = int.Parse(e.TheMovieDbId),
|
ContentId = StringHelper.IntParseLinq(e.TheMovieDbId),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,7 +212,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
AddedAt = DateTime.Now,
|
AddedAt = DateTime.Now,
|
||||||
Type = RecentlyAddedType.Emby,
|
Type = RecentlyAddedType.Emby,
|
||||||
ContentType = ContentType.Episode,
|
ContentType = ContentType.Episode,
|
||||||
ContentId = int.Parse(p.Series.TvDbId),
|
ContentId = StringHelper.IntParseLinq(p.Series.TvDbId),
|
||||||
EpisodeNumber = p.EpisodeNumber,
|
EpisodeNumber = p.EpisodeNumber,
|
||||||
SeasonNumber = p.SeasonNumber
|
SeasonNumber = p.SeasonNumber
|
||||||
});
|
});
|
||||||
|
@ -260,7 +260,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
var itemsToReturn = new HashSet<PlexEpisode>();
|
var itemsToReturn = new HashSet<PlexEpisode>();
|
||||||
foreach (var ep in source)
|
foreach (var ep in source)
|
||||||
{
|
{
|
||||||
var tvDbId = int.Parse(ep.Series.TvDbId);
|
var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId);
|
||||||
if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber))
|
if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -277,7 +277,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
var itemsToReturn = new HashSet<EmbyEpisode>();
|
var itemsToReturn = new HashSet<EmbyEpisode>();
|
||||||
foreach (var ep in source)
|
foreach (var ep in source)
|
||||||
{
|
{
|
||||||
var tvDbId = int.Parse(ep.Series.TvDbId);
|
var tvDbId = StringHelper.IntParseLinq(ep.Series.TvDbId);
|
||||||
if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber))
|
if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -406,8 +406,8 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
theMovieDbId = result.id.ToString();
|
theMovieDbId = result.id.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
var info = await _movieApi.GetMovieInformationWithExtraInfo(int.Parse(theMovieDbId));
|
|
||||||
var mediaurl = content.Url;
|
var mediaurl = content.Url;
|
||||||
|
var info = await _movieApi.GetMovieInformationWithExtraInfo(StringHelper.IntParseLinq(theMovieDbId));
|
||||||
if (info == null)
|
if (info == null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -12,5 +12,6 @@ namespace Ombi.Settings.Settings.Models
|
||||||
public bool RequireLowercase { get; set; }
|
public bool RequireLowercase { get; set; }
|
||||||
public bool RequireNonAlphanumeric { get; set; }
|
public bool RequireNonAlphanumeric { get; set; }
|
||||||
public bool RequireUppercase { get; set; }
|
public bool RequireUppercase { get; set; }
|
||||||
|
public bool EnableOAuth { get; set; } // Plex OAuth
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -145,6 +145,7 @@ export interface IAuthenticationSettings extends ISettings {
|
||||||
requiredLowercase: boolean;
|
requiredLowercase: boolean;
|
||||||
requireNonAlphanumeric: boolean;
|
requireNonAlphanumeric: boolean;
|
||||||
requireUppercase: boolean;
|
requireUppercase: boolean;
|
||||||
|
enableOAuth: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IUserManagementSettings extends ISettings {
|
export interface IUserManagementSettings extends ISettings {
|
||||||
|
|
|
@ -17,7 +17,7 @@ include the remember me checkbox
|
||||||
</div>
|
</div>
|
||||||
<p id="profile-name" class="profile-name-card"></p>
|
<p id="profile-name" class="profile-name-card"></p>
|
||||||
|
|
||||||
<div *ngIf="!plexEnabled || !customizationSettings.applicationUrl || loginWithOmbi">
|
<div *ngIf="!authenticationSettings.enableOAuth || loginWithOmbi">
|
||||||
<form *ngIf="authenticationSettings" class="form-signin" novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
|
<form *ngIf="authenticationSettings" class="form-signin" novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,15 +41,16 @@ include the remember me checkbox
|
||||||
<!-- /form -->
|
<!-- /form -->
|
||||||
</div>
|
</div>
|
||||||
<!-- Main OAuth Flow -->
|
<!-- Main OAuth Flow -->
|
||||||
<div class="form-signin" *ngIf="plexEnabled && customizationSettings.applicationUrl && !loginWithOmbi">
|
<div *ngIf="authenticationSettings.enableOAuth && !loginWithOmbi">
|
||||||
|
<div class="form-signin">
|
||||||
<button class="btn btn-success" type="button" (click)="loginWithOmbi = true">
|
<button class="btn btn-success" type="button" (click)="loginWithOmbi = true">
|
||||||
Sign In With {{appName}}</button>
|
Sign In With {{appName}}</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-signin" *ngIf="plexEnabled && customizationSettings.applicationUrl && !loginWithOmbi">
|
<div class="form-signin">
|
||||||
<button class="btn btn-primary" type="button" (click)="oauth()">
|
<button class="btn btn-primary" type="button" (click)="oauth()">
|
||||||
Sign In With Plex</button>
|
Sign In With Plex</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- /card-container -->
|
<!-- /card-container -->
|
||||||
|
|
|
@ -79,7 +79,6 @@ export class LoginComponent implements OnDestroy, OnInit {
|
||||||
public ngOnInit() {
|
public ngOnInit() {
|
||||||
this.settingsService.getAuthentication().subscribe(x => this.authenticationSettings = x);
|
this.settingsService.getAuthentication().subscribe(x => this.authenticationSettings = x);
|
||||||
this.settingsService.getCustomization().subscribe(x => this.customizationSettings = x);
|
this.settingsService.getCustomization().subscribe(x => this.customizationSettings = x);
|
||||||
this.settingsService.getStatusPlex().subscribe(x => this.plexEnabled = x);
|
|
||||||
this.images.getRandomBackground().subscribe(x => {
|
this.images.getRandomBackground().subscribe(x => {
|
||||||
this.background = this.sanitizer.bypassSecurityTrustStyle("linear-gradient(-10deg, transparent 20%, rgba(0,0,0,0.7) 20.0%, rgba(0,0,0,0.7) 80.0%, transparent 80%),url(" + x.url + ")");
|
this.background = this.sanitizer.bypassSecurityTrustStyle("linear-gradient(-10deg, transparent 20%, rgba(0,0,0,0.7) 20.0%, rgba(0,0,0,0.7) 80.0%, transparent 80%),url(" + x.url + ")");
|
||||||
});
|
});
|
||||||
|
@ -125,7 +124,13 @@ export class LoginComponent implements OnDestroy, OnInit {
|
||||||
|
|
||||||
public oauth() {
|
public oauth() {
|
||||||
this.authService.login({usePlexOAuth: true, password:"",rememberMe:true,username:""}).subscribe(x => {
|
this.authService.login({usePlexOAuth: true, password:"",rememberMe:true,username:""}).subscribe(x => {
|
||||||
window.location.href = x.url;
|
if (window.frameElement) {
|
||||||
|
// in frame
|
||||||
|
window.open(x.url, "_blank");
|
||||||
|
} else {
|
||||||
|
// not in frame
|
||||||
|
window.location.href = x.url;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
|
|
||||||
import { AuthService } from "../auth/auth.service";
|
import { AuthService } from "../auth/auth.service";
|
||||||
|
import { NotificationService } from "../services";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: "./loginoauth.component.html",
|
templateUrl: "./loginoauth.component.html",
|
||||||
|
@ -11,7 +12,7 @@ export class LoginOAuthComponent implements OnInit {
|
||||||
public error: string;
|
public error: string;
|
||||||
|
|
||||||
constructor(private authService: AuthService, private router: Router,
|
constructor(private authService: AuthService, private router: Router,
|
||||||
private route: ActivatedRoute) {
|
private route: ActivatedRoute, private notify: NotificationService) {
|
||||||
this.route.params
|
this.route.params
|
||||||
.subscribe((params: any) => {
|
.subscribe((params: any) => {
|
||||||
this.pin = params.pin;
|
this.pin = params.pin;
|
||||||
|
@ -37,6 +38,10 @@ export class LoginOAuthComponent implements OnInit {
|
||||||
this.error = x.errorMessage;
|
this.error = x.errorMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}, err => {
|
||||||
|
this.notify.error(err.statusText);
|
||||||
|
|
||||||
|
this.router.navigate(["login"]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
|
|
||||||
<div infinite-scroll [infiniteScrollDistance]="1" [infiniteScrollThrottle]="100" (scrolled)="loadMore()">
|
<div>
|
||||||
|
|
||||||
|
|
||||||
<div *ngFor="let request of movieRequests | orderBy: order : reverse : 'case-insensitive'">
|
<div *ngFor="let request of movieRequests | orderBy: order : reverse : 'case-insensitive'">
|
||||||
|
@ -212,6 +212,8 @@
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<p-paginator [rows]="10" [totalRecords]="totalMovies" (onPageChange)="paginate($event)"></p-paginator>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { Subject } from "rxjs/Subject";
|
||||||
import { AuthService } from "../auth/auth.service";
|
import { AuthService } from "../auth/auth.service";
|
||||||
import { NotificationService, RadarrService, RequestService } from "../services";
|
import { NotificationService, RadarrService, RequestService } from "../services";
|
||||||
|
|
||||||
import { FilterType, IFilter, IIssueCategory, IMovieRequests, IRadarrProfile, IRadarrRootFolder } from "../interfaces";
|
import { FilterType, IFilter, IIssueCategory, IMovieRequests, IPagenator, IRadarrProfile, IRadarrRootFolder } from "../interfaces";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "movie-requests",
|
selector: "movie-requests",
|
||||||
|
@ -39,6 +39,7 @@ export class MovieRequestsComponent implements OnInit {
|
||||||
public order: string = "requestedDate";
|
public order: string = "requestedDate";
|
||||||
public reverse = false;
|
public reverse = false;
|
||||||
|
|
||||||
|
public totalMovies: number = 100;
|
||||||
private currentlyLoaded: number;
|
private currentlyLoaded: number;
|
||||||
private amountToLoad: number;
|
private amountToLoad: number;
|
||||||
|
|
||||||
|
@ -65,8 +66,8 @@ export class MovieRequestsComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnInit() {
|
public ngOnInit() {
|
||||||
this.amountToLoad = 100;
|
this.amountToLoad = 10;
|
||||||
this.currentlyLoaded = 100;
|
this.currentlyLoaded = 10;
|
||||||
this.loadInit();
|
this.loadInit();
|
||||||
this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser");
|
this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser");
|
||||||
this.filter = {
|
this.filter = {
|
||||||
|
@ -74,8 +75,10 @@ export class MovieRequestsComponent implements OnInit {
|
||||||
statusFilter: FilterType.None};
|
statusFilter: FilterType.None};
|
||||||
}
|
}
|
||||||
|
|
||||||
public loadMore() {
|
public paginate(event: IPagenator) {
|
||||||
this.loadRequests(this.amountToLoad, this.currentlyLoaded);
|
const skipAmount = event.first;
|
||||||
|
|
||||||
|
this.loadRequests(this.amountToLoad, skipAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public search(text: any) {
|
public search(text: any) {
|
||||||
|
@ -226,7 +229,7 @@ export class MovieRequestsComponent implements OnInit {
|
||||||
if(!this.movieRequests) {
|
if(!this.movieRequests) {
|
||||||
this.movieRequests = [];
|
this.movieRequests = [];
|
||||||
}
|
}
|
||||||
this.movieRequests.push.apply(this.movieRequests, x);
|
this.movieRequests = x;
|
||||||
this.currentlyLoaded = currentlyLoaded + amountToLoad;
|
this.currentlyLoaded = currentlyLoaded + amountToLoad;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -267,6 +270,7 @@ export class MovieRequestsComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadInit() {
|
private loadInit() {
|
||||||
|
this.requestService.getTotalMovies().subscribe(x => this.totalMovies = x);
|
||||||
this.requestService.getMovieRequests(this.amountToLoad, 0)
|
this.requestService.getMovieRequests(this.amountToLoad, 0)
|
||||||
.subscribe(x => {
|
.subscribe(x => {
|
||||||
this.movieRequests = x;
|
this.movieRequests = x;
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { OrderModule } from "ngx-order-pipe";
|
||||||
|
|
||||||
import { InfiniteScrollModule } from "ngx-infinite-scroll";
|
import { InfiniteScrollModule } from "ngx-infinite-scroll";
|
||||||
|
|
||||||
import { ButtonModule, DialogModule } from "primeng/primeng";
|
import { ButtonModule, DialogModule, PaginatorModule } from "primeng/primeng";
|
||||||
import { MovieRequestsComponent } from "./movierequests.component";
|
import { MovieRequestsComponent } from "./movierequests.component";
|
||||||
// Request
|
// Request
|
||||||
import { RequestComponent } from "./request.component";
|
import { RequestComponent } from "./request.component";
|
||||||
|
@ -36,6 +36,7 @@ const routes: Routes = [
|
||||||
SharedModule,
|
SharedModule,
|
||||||
SidebarModule,
|
SidebarModule,
|
||||||
OrderModule,
|
OrderModule,
|
||||||
|
PaginatorModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
RequestComponent,
|
RequestComponent,
|
||||||
|
|
|
@ -120,6 +120,7 @@
|
||||||
</p-column>
|
</p-column>
|
||||||
</p-treeTable>
|
</p-treeTable>
|
||||||
|
|
||||||
|
<p-paginator [rows]="10" [totalRecords]="totalTv" (onPageChange)="paginate($event)"></p-paginator>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<issue-report [movie]="false" [visible]="issuesBarVisible" [title]="issueRequest?.title"
|
<issue-report [movie]="false" [visible]="issuesBarVisible" [title]="issueRequest?.title"
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { AuthService } from "../auth/auth.service";
|
||||||
import { NotificationService, RequestService, SonarrService } from "../services";
|
import { NotificationService, RequestService, SonarrService } from "../services";
|
||||||
|
|
||||||
import { TreeNode } from "primeng/primeng";
|
import { TreeNode } from "primeng/primeng";
|
||||||
import { IIssueCategory, ISonarrProfile, ISonarrRootFolder, ITvRequests } from "../interfaces";
|
import { IIssueCategory, IPagenator, ISonarrProfile, ISonarrRootFolder, ITvRequests } from "../interfaces";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "tv-requests",
|
selector: "tv-requests",
|
||||||
|
@ -40,6 +40,7 @@ export class TvRequestsComponent implements OnInit {
|
||||||
public sonarrProfiles: ISonarrProfile[] = [];
|
public sonarrProfiles: ISonarrProfile[] = [];
|
||||||
public sonarrRootFolders: ISonarrRootFolder[] = [];
|
public sonarrRootFolders: ISonarrRootFolder[] = [];
|
||||||
|
|
||||||
|
public totalTv: number = 100;
|
||||||
private currentlyLoaded: number;
|
private currentlyLoaded: number;
|
||||||
private amountToLoad: number;
|
private amountToLoad: number;
|
||||||
|
|
||||||
|
@ -105,25 +106,22 @@ export class TvRequestsComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnInit() {
|
public ngOnInit() {
|
||||||
this.amountToLoad = 1000;
|
this.amountToLoad = 10;
|
||||||
this.currentlyLoaded = 1000;
|
this.currentlyLoaded = 10;
|
||||||
this.tvRequests = [];
|
this.tvRequests = [];
|
||||||
this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser");
|
this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser");
|
||||||
|
|
||||||
this.loadInit();
|
this.loadInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public loadMore() {
|
public paginate(event: IPagenator) {
|
||||||
//TODO: I believe this +1 is causing off by one error skipping loading of tv shows
|
const skipAmount = event.first;
|
||||||
//When removed and scrolling very slowly everything works as expected, however
|
|
||||||
//if you scroll really quickly then you start getting duplicates of movies
|
this.requestService.getTvRequestsTree(this.amountToLoad, skipAmount)
|
||||||
//since it's async and some subsequent results return first and then incrementer
|
.subscribe(x => {
|
||||||
//is increased so you see movies which had already been gotten show up...
|
this.tvRequests = x;
|
||||||
this.requestService.getTvRequestsTree(this.amountToLoad, this.currentlyLoaded + 1)
|
this.currentlyLoaded = this.currentlyLoaded + this.amountToLoad;
|
||||||
.subscribe(x => {
|
});
|
||||||
this.tvRequests = x;
|
|
||||||
this.currentlyLoaded = this.currentlyLoaded + this.amountToLoad;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public search(text: any) {
|
public search(text: any) {
|
||||||
|
@ -197,6 +195,7 @@ export class TvRequestsComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadInit() {
|
private loadInit() {
|
||||||
|
this.requestService.getTotalTv().subscribe(x => this.totalTv = x);
|
||||||
this.requestService.getTvRequestsTree(this.amountToLoad, 0)
|
this.requestService.getTvRequestsTree(this.amountToLoad, 0)
|
||||||
.subscribe(x => {
|
.subscribe(x => {
|
||||||
this.tvRequests = x;
|
this.tvRequests = x;
|
||||||
|
|
|
@ -20,6 +20,14 @@ export class RequestService extends ServiceHelpers {
|
||||||
return this.http.post<IRequestEngineResult>(`${this.url}Movie/`, JSON.stringify(movie), {headers: this.headers});
|
return this.http.post<IRequestEngineResult>(`${this.url}Movie/`, JSON.stringify(movie), {headers: this.headers});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getTotalMovies(): Observable<number> {
|
||||||
|
return this.http.get<number>(`${this.url}Movie/total`, {headers: this.headers});
|
||||||
|
}
|
||||||
|
|
||||||
|
public getTotalTv(): Observable<number> {
|
||||||
|
return this.http.get<number>(`${this.url}tv/total`, {headers: this.headers});
|
||||||
|
}
|
||||||
|
|
||||||
public requestTv(tv: ITvRequestViewModel): Observable<IRequestEngineResult> {
|
public requestTv(tv: ITvRequestViewModel): Observable<IRequestEngineResult> {
|
||||||
return this.http.post<IRequestEngineResult>(`${this.url}TV/`, JSON.stringify(tv), {headers: this.headers});
|
return this.http.post<IRequestEngineResult>(`${this.url}TV/`, JSON.stringify(tv), {headers: this.headers});
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,10 +71,6 @@ export class SettingsService extends ServiceHelpers {
|
||||||
return this.http.get<IPlexSettings>(`${this.url}/Plex/`, {headers: this.headers});
|
return this.http.get<IPlexSettings>(`${this.url}/Plex/`, {headers: this.headers});
|
||||||
}
|
}
|
||||||
|
|
||||||
public getStatusPlex(): Observable<boolean> {
|
|
||||||
return this.http.get<boolean>(`${this.url}/Plexstatus/`, {headers: this.headers});
|
|
||||||
}
|
|
||||||
|
|
||||||
public savePlex(settings: IPlexSettings): Observable<boolean> {
|
public savePlex(settings: IPlexSettings): Observable<boolean> {
|
||||||
return this.http.post<boolean>(`${this.url}/Plex/`, JSON.stringify(settings), {headers: this.headers});
|
return this.http.post<boolean>(`${this.url}/Plex/`, JSON.stringify(settings), {headers: this.headers});
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="checkbox">
|
||||||
|
<input type="checkbox" id="enableOAuth" name="enableOAuth" formControlName="enableOAuth">
|
||||||
|
<label for="enableOAuth" >Enable Plex OAuth</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- <hr/>
|
<!-- <hr/>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
|
|
|
@ -24,6 +24,7 @@ export class AuthenticationComponent implements OnInit {
|
||||||
requiredLowercase: [x.requiredLowercase],
|
requiredLowercase: [x.requiredLowercase],
|
||||||
requireNonAlphanumeric: [x.requireNonAlphanumeric],
|
requireNonAlphanumeric: [x.requireNonAlphanumeric],
|
||||||
requireUppercase: [x.requireUppercase],
|
requireUppercase: [x.requireUppercase],
|
||||||
|
enableOAuth: [x.enableOAuth],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -959,3 +959,7 @@ a > h4:hover {
|
||||||
width: 94%;
|
width: 94%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui-state-active {
|
||||||
|
background-color: $primary-colour-outline $i;
|
||||||
|
color: black $i;
|
||||||
|
}
|
|
@ -37,6 +37,15 @@ namespace Ombi.Controllers
|
||||||
return await MovieRequestEngine.GetRequests(count, position);
|
return await MovieRequestEngine.GetRequests(count, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the total amount of movie requests.
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("movie/total")]
|
||||||
|
public async Task<int> GetTotalMovies()
|
||||||
|
{
|
||||||
|
return await MovieRequestEngine.GetTotal();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all movie requests.
|
/// Gets all movie requests.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -146,6 +155,15 @@ namespace Ombi.Controllers
|
||||||
return await TvRequestEngine.GetRequestsTreeNode(count, position);
|
return await TvRequestEngine.GetRequestsTreeNode(count, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the total amount of TV requests.
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("tv/total")]
|
||||||
|
public async Task<int> GetTotalTV()
|
||||||
|
{
|
||||||
|
return await TvRequestEngine.GetTotal();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the tv requests.
|
/// Gets the tv requests.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -147,16 +147,6 @@ namespace Ombi.Controllers
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("plexstatus")]
|
|
||||||
[AllowAnonymous]
|
|
||||||
public async Task<bool> PlexStatusSettings()
|
|
||||||
{
|
|
||||||
var s = await Get<PlexSettings>();
|
|
||||||
|
|
||||||
|
|
||||||
return s.Enable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Save the Plex settings.
|
/// Save the Plex settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace Ombi.Controllers
|
||||||
{
|
{
|
||||||
[ApiV1]
|
[ApiV1]
|
||||||
[Produces("application/json")]
|
[Produces("application/json")]
|
||||||
public class TokenController
|
public class TokenController : Controller
|
||||||
{
|
{
|
||||||
public TokenController(OmbiUserManager um, IOptions<TokenAuthentication> ta, IAuditRepository audit, ITokenRepository token,
|
public TokenController(OmbiUserManager um, IOptions<TokenAuthentication> ta, IAuditRepository audit, ITokenRepository token,
|
||||||
IPlexOAuthManager oAuthManager)
|
IPlexOAuthManager oAuthManager)
|
||||||
|
@ -83,8 +83,9 @@ namespace Ombi.Controllers
|
||||||
// We need a PIN first
|
// We need a PIN first
|
||||||
var pin = await _plexOAuthManager.RequestPin();
|
var pin = await _plexOAuthManager.RequestPin();
|
||||||
|
|
||||||
|
var websiteAddress = $"{this.Request.Scheme}://{this.Request.Host}{this.Request.PathBase}";
|
||||||
//https://app.plex.tv/auth#?forwardUrl=http://google.com/&clientID=Ombi-Test&context%5Bdevice%5D%5Bproduct%5D=Ombi%20SSO&pinID=798798&code=4lgfd
|
//https://app.plex.tv/auth#?forwardUrl=http://google.com/&clientID=Ombi-Test&context%5Bdevice%5D%5Bproduct%5D=Ombi%20SSO&pinID=798798&code=4lgfd
|
||||||
var url = await _plexOAuthManager.GetOAuthUrl(pin.id, pin.code);
|
var url = await _plexOAuthManager.GetOAuthUrl(pin.id, pin.code, websiteAddress);
|
||||||
if (url == null)
|
if (url == null)
|
||||||
{
|
{
|
||||||
return new JsonResult(new
|
return new JsonResult(new
|
||||||
|
|
|
@ -134,7 +134,7 @@ namespace Ombi
|
||||||
{
|
{
|
||||||
x.UseSQLiteStorage(sqliteStorage);
|
x.UseSQLiteStorage(sqliteStorage);
|
||||||
x.UseActivator(new IoCJobActivator(services.BuildServiceProvider()));
|
x.UseActivator(new IoCJobActivator(services.BuildServiceProvider()));
|
||||||
x.UseConsole();
|
//x.UseConsole();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue