Merge branch 'develop' into snyk-upgrade-52165cf7d6fcba49d335a55559b6584d

snyk-upgrade-52165cf7d6fcba49d335a55559b6584d
Jamie Rees 3 months ago committed by GitHub
commit d03af88bcf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,3 +1,12 @@
## [4.45.1](https://github.com/Ombi-app/Ombi/compare/v4.45.0...v4.45.1) (2024-08-20)
### Bug Fixes
* **plex:** Fixed some errors around the scanner that was causing the scan to fail ([d9787dc](https://github.com/Ombi-app/Ombi/commit/d9787dc32aace808d196f6f87456ef45de3d7bbf))
# [4.45.0](https://github.com/Ombi-app/Ombi/compare/v4.44.1...v4.45.0) (2024-08-07)
@ -3717,12 +3726,3 @@
# [4.37.0](https://github.com/Ombi-app/Ombi/compare/v4.36.1...v4.37.0) (2023-04-24)
### Features
* Search by genre ([1837419](https://github.com/Ombi-app/Ombi/commit/18374198f9f2462ba85c5781b0fcc05892728b21))

@ -7,6 +7,7 @@ using Microsoft.Extensions.Logging;
using Ombi.Api.Emby;
using Ombi.Api.Jellyfin;
using Ombi.Api.Plex;
using Ombi.Api.Plex.Models;
using Ombi.Api.TheMovieDb;
using Ombi.Api.TheMovieDb.Models;
using Ombi.Api.TvMaze;
@ -286,7 +287,18 @@ namespace Ombi.Schedule.Jobs.Ombi
continue;
}
var servers = settings.Servers[0];
var metaData = await _plexApi.GetMetadata(servers.PlexAuthToken, settings.Servers[0].FullUri, movie.Key);
PlexMetadata metaData = null;
try
{
metaData = await _plexApi.GetMetadata(servers.PlexAuthToken, settings.Servers[0].FullUri, movie.Key);
}
catch (Exception e)
{
_log.LogError($"Could not find the metadata for title: '{movie.Title}', skipping");
_log.LogDebug(e, $"Could not find the metadata for title: '{movie.Title}', skipping");
continue;
}
var guids = new List<string>();
var meta = metaData.MediaContainer.Metadata.FirstOrDefault();

@ -304,6 +304,13 @@ namespace Ombi.Schedule.Jobs.Plex
var existing = await Repo.GetFirstContentByCustom(x => x.Title == movie.title
&& x.ReleaseYear == movie.year.ToString()
&& x.Type == MediaType.Movie);
if (existing == null)
{
// Let's just check the key
existing = await Repo.GetByKey(movie.ratingKey);
}
if (existing != null)
{
// We need to see if this is a different quality,
@ -342,12 +349,6 @@ namespace Ombi.Schedule.Jobs.Plex
continue;
}
//var hasSameKey = await Repo.GetByKey(movie.ratingKey);
//if (hasSameKey != null)
//{
// await Repo.Delete(hasSameKey);
//}
Logger.LogDebug("Adding movie {0}", movie.title);
var guids = new List<string>();
if (!movie.Guid.Any())

@ -19,7 +19,7 @@
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.5" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.22" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
<PackageReference Include="Nito.AsyncEx" Version="5.1.2" />
<PackageReference Include="Polly" Version="7.2.3" />

@ -94,7 +94,7 @@ namespace Ombi.Store.Repository
public async Task<PlexServerContent> GetByKey(string key)
{
return await Db.PlexServerContent.Include(x => x.Seasons).FirstOrDefaultAsync(x => x.Key == key);
return await Db.PlexServerContent.Include(x => x.Seasons).Include(x => x.Episodes).FirstOrDefaultAsync(x => x.Key == key);
}
public IEnumerable<PlexServerContent> GetWhereContentByCustom(Expression<Func<PlexServerContent, bool>> predicate)

@ -29,7 +29,7 @@
"@fortawesome/fontawesome-free": "^6.6.0",
"@microsoft/signalr": "^6.0.23",
"@ngx-translate/core": "^15.0.0",
"@ngx-translate/http-loader": "^7.0.0",
"@ngx-translate/http-loader": "^8.0.0",
"@ngxs/devtools-plugin": "3.8.2",
"@ngxs/store": "3.8.2",
"@types/jquery": "^3.5.30",

@ -5,9 +5,13 @@
<mat-button-toggle id="{{id}}Tv" [ngClass]="{'button-active': discoverOptions === DiscoverOption.Tv}" value="{{DiscoverOption.Tv}}" class="discover-filter-button">{{'Discovery.Tv' | translate}}</mat-button-toggle>
</mat-button-toggle-group>
</div>
@defer (when discoverResults.length > 0) {
<p-carousel #carousel [numVisible]="10" [numScroll]="10" [page]="0" [value]="discoverResults" [responsiveOptions]="responsiveOptions" (onPage)="newPage()">
<ng-template let-result pTemplate="item">
<discover-card [discoverType]="discoverType" [isAdmin]="isAdmin" [result]="result" [is4kEnabled]="is4kEnabled"></discover-card>
</ng-template>
</p-carousel>
}
@placeholder(minimum 500) {
<p-skeleton width="100%" height="18rem"></p-skeleton>
}

@ -1,12 +1,7 @@
<div class="small-middle-container">
<div class="section">
@defer (on viewport; prefetch on idle) {
<h2 id="genreHeading" data-toggle="collapse" href="#genreCollapse" role="button">{{ 'Discovery.Genres' | translate }}</h2>
<genre-button-select class="collapse show" id="genreCollapse"></genre-button-select>
}
@placeholder {
<p-skeleton width="100%" height="2rem"></p-skeleton>
}
</div>
<div class="section">
<h2>{{ 'Discovery.RecentlyRequestedTab' | translate }}</h2>

@ -1,13 +1,26 @@
<div class="genre-container" *ngIf="movieGenreList$ | async as movies">
<mat-button-toggle-group name="discoverMode" (change)="toggleChanged($event, genre.type)" *ngFor="let genre of movies"
class="discover-filter-buttons-group">
<mat-button-toggle value="{{genre.id}}" class="discover-filter-button">{{genre.name}}</mat-button-toggle>
</mat-button-toggle-group>
</div>
<div class="genre-container" *ngIf="tvGenreList$ | async as tv">
<mat-button-toggle-group name="discoverMode" (change)="toggleChanged($event, genre.type)" *ngFor="let genre of tv"
class="discover-filter-buttons-group">
<mat-button-toggle value="{{genre.id}}" class="discover-filter-button">{{genre.name}}</mat-button-toggle>
</mat-button-toggle-group>
<mat-spinner *ngIf="isLoading" [diameter]="30"></mat-spinner>
</div>
@defer (when movieGenreList()) {
<div class="genre-container">
<mat-button-toggle-group name="discoverMode" (change)="toggleChanged($event, genre.type)" *ngFor="let genre of movieGenreList()"
class="discover-filter-buttons-group">
<mat-button-toggle value="{{genre.id}}" class="discover-filter-button">{{genre.name}}</mat-button-toggle>
</mat-button-toggle-group>
</div>
}
@placeholder(minimum 500) {
<p-skeleton width="100%" height="3.5rem"></p-skeleton>
}
@defer (when tvGenreList()) {
<div class="genre-container">
<mat-button-toggle-group name="discoverMode" (change)="toggleChanged($event, genre.type)" *ngFor="let genre of tvGenreList()"
class="discover-filter-buttons-group">
<mat-button-toggle value="{{genre.id}}" class="discover-filter-button">{{genre.name}}</mat-button-toggle>
</mat-button-toggle-group>
</div>
}
@placeholder(minimum 500) {
<p-skeleton width="100%" height="3.5rem"></p-skeleton>
}
<mat-spinner *ngIf="isLoading" [diameter]="30"></mat-spinner>

@ -1,10 +1,11 @@
import { Component, OnInit } from "@angular/core";
import { Component, OnInit, computed, signal } from "@angular/core";
import { SearchV2Service } from "../../../services";
import { MatButtonToggleChange } from "@angular/material/button-toggle";
import { RequestType } from "../../../interfaces";
import { AdvancedSearchDialogDataService } from "app/shared/advanced-search-dialog/advanced-search-dialog-data.service";
import { Router } from "@angular/router";
import { map, Observable } from "rxjs";
import { toSignal } from '@angular/core/rxjs-interop';
interface IGenreSelect {
name: string;
@ -17,8 +18,10 @@ interface IGenreSelect {
styleUrls: ["./genre-button-select.component.scss"],
})
export class GenreButtonSelectComponent implements OnInit {
public movieGenreList$: Observable<IGenreSelect[]> = null;
public tvGenreList$: Observable<IGenreSelect[]> = null;
public movieGenreList = signal<IGenreSelect[]>(null);
public tvGenreList = signal<IGenreSelect[]>(null);
isLoading: boolean = false;
@ -27,8 +30,14 @@ export class GenreButtonSelectComponent implements OnInit {
private router: Router) { }
public ngOnInit(): void {
this.movieGenreList$ = this.searchService.getGenres("movie").pipe(map(x => x.slice(0, 10).map(y => ({ name: y.name, id: y.id, type: "movie" }))));
this.tvGenreList$ = this.searchService.getGenres("tv").pipe(map(x => x.slice(0, 10).map(y => ({ name: y.name, id: y.id, type: "tv" }))));
this.searchService.getGenres("movie").pipe(map(x => x.slice(0, 10).map(y => ({ name: y.name, id: y.id, type: "movie" } as IGenreSelect))))
.subscribe(x => {
this.movieGenreList.set(x);
});
this.searchService.getGenres("tv").pipe(map(x => x.slice(0, 10).map(y => ({ name: y.name, id: y.id, type: "tv" } as IGenreSelect))))
.subscribe(x => {
this.tvGenreList.set(x);
});
}
public async toggleChanged(event: MatButtonToggleChange, type: "movie"|"tv") {

@ -1,9 +1,8 @@
<div *ngIf="requests$ | async as requests">
<div *ngIf="requests.length > 0">
<p-carousel #carousel [value]="requests" [numVisible]="3" [numScroll]="1"
@defer (when requests()) {
<div *ngIf="requests().length > 0">
<p-carousel #carousel [value]="requests()" [numVisible]="3" [numScroll]="1"
[responsiveOptions]="responsiveOptions" [page]="0">
<ng-template let-result pTemplate="item">
@defer (on viewport; prefetch on idle) {
<ombi-detailed-card
[request]="result"
[isAdmin]="isAdmin"
@ -11,11 +10,25 @@
(onApprove)="approve(result)"
(onDeny)="deny(result)">
</ombi-detailed-card>
}
@placeholder {
<p-skeleton width="100%" height="315px"></p-skeleton>
}
</ng-template>
</p-carousel>
</div>
</div>
}@placeholder(minimum 500) {
<div class="row loading-container">
<div class="col-2">
<p-skeleton width="100%" height="270px"></p-skeleton>
</div>
<div class="col-2">
<p-skeleton width="100%" height="270px"></p-skeleton>
</div>
<div class="col-2">
<p-skeleton width="100%" height="270px"></p-skeleton>
</div>
<div class="col-2">
<p-skeleton width="100%" height="270px"></p-skeleton>
</div>
<div class="col-2">
<p-skeleton width="100%" height="270px"></p-skeleton>
</div>
</div>
}

@ -110,3 +110,7 @@
flex: 1 0 200px !important;
}
}
.loading-container {
margin-left: 10rem;
}

@ -1,4 +1,4 @@
import { Component, OnInit, Input, ViewChild, OnDestroy } from "@angular/core";
import { Component, OnInit, Input, ViewChild, OnDestroy, signal } from "@angular/core";
import { IRecentlyRequested, IRequestEngineResult, RequestType } from "../../../interfaces";
import { Carousel } from 'primeng/carousel';
import { ResponsiveOptions } from "../carousel.options";
@ -31,6 +31,7 @@ export class RecentlyRequestedListComponent implements OnInit, OnDestroy {
@ViewChild('carousel', {static: false}) carousel: Carousel;
public requests$: Observable<IRecentlyRequested[]>;
public requests = signal<IRecentlyRequested[]>(null);
public responsiveOptions: any;
public RequestType = RequestType;
@ -119,11 +120,13 @@ export class RecentlyRequestedListComponent implements OnInit, OnDestroy {
}
private loadData() {
this.requests$ = this.requestServiceV2.getRecentlyRequested().pipe(
this.requestServiceV2.getRecentlyRequested().pipe(
tap(() => this.loading()),
takeUntil(this.$loadSub),
finalize(() => this.finishLoading())
);
).subscribe(x => {
this.requests.set(x);
});
}
private loading() {

@ -2086,12 +2086,10 @@
resolved "https://registry.yarnpkg.com/@ngx-translate/core/-/core-15.0.0.tgz#0fe55b9bd47e75b03d1123658f15fb7b5a534f3c"
integrity sha512-Am5uiuR0bOOxyoercDnAA3rJVizo4RRqJHo8N3RqJ+XfzVP/I845yEnMADykOHvM6HkVm4SZSnJBOiz0Anx5BA==
"@ngx-translate/http-loader@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/@ngx-translate/http-loader/-/http-loader-7.0.0.tgz#905f38d8d13342621516635bf480ff9a4f73e9fc"
integrity sha512-j+NpXXlcGVdyUNyY/qsJrqqeAdJdizCd+GKh3usXExSqy1aE9866jlAIL+xrfDU4w+LiMoma5pgE4emvFebZmA==
dependencies:
tslib "^2.3.0"
"@ngx-translate/http-loader@^8.0.0":
version "8.0.0"
resolved "https://registry.yarnpkg.com/@ngx-translate/http-loader/-/http-loader-8.0.0.tgz#e02c25dbe33c6b1edee73e3654ab8a161572cdfb"
integrity sha512-SFMsdUcmHF5OdZkL1CHEoSAwbP5EbAOPTLLboOCRRoOg21P4GJx+51jxGdJeGve6LSKLf4Pay7BkTwmE6vxYlg==
"@ngxs/devtools-plugin@3.8.2":
version "3.8.2"

@ -1,3 +1,3 @@
{
"version": "4.45.0"
"version": "4.45.1"
}

Loading…
Cancel
Save