mirror of https://github.com/ErsatzTV/ErsatzTV.git
Browse Source
* plex api cleanup * improve plex movie scanner * sync plex collections as tags * improve plex tv library scanner * update dependencies * fix plex season and episode collection tagspull/748/head
31 changed files with 5079 additions and 374 deletions
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
namespace ErsatzTV.Core.Plex; |
||||
|
||||
public class PlexItemEtag |
||||
{ |
||||
public string Key { get; set; } |
||||
public string Etag { get; set; } |
||||
} |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,55 @@
@@ -0,0 +1,55 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
||||
#nullable disable |
||||
|
||||
namespace ErsatzTV.Infrastructure.Migrations |
||||
{ |
||||
public partial class Add_PlexEtags : Migration |
||||
{ |
||||
protected override void Up(MigrationBuilder migrationBuilder) |
||||
{ |
||||
migrationBuilder.AddColumn<string>( |
||||
name: "Etag", |
||||
table: "PlexShow", |
||||
type: "TEXT", |
||||
nullable: true); |
||||
|
||||
migrationBuilder.AddColumn<string>( |
||||
name: "Etag", |
||||
table: "PlexSeason", |
||||
type: "TEXT", |
||||
nullable: true); |
||||
|
||||
migrationBuilder.AddColumn<string>( |
||||
name: "Etag", |
||||
table: "PlexMovie", |
||||
type: "TEXT", |
||||
nullable: true); |
||||
|
||||
migrationBuilder.AddColumn<string>( |
||||
name: "Etag", |
||||
table: "PlexEpisode", |
||||
type: "TEXT", |
||||
nullable: true); |
||||
} |
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder) |
||||
{ |
||||
migrationBuilder.DropColumn( |
||||
name: "Etag", |
||||
table: "PlexShow"); |
||||
|
||||
migrationBuilder.DropColumn( |
||||
name: "Etag", |
||||
table: "PlexSeason"); |
||||
|
||||
migrationBuilder.DropColumn( |
||||
name: "Etag", |
||||
table: "PlexMovie"); |
||||
|
||||
migrationBuilder.DropColumn( |
||||
name: "Etag", |
||||
table: "PlexEpisode"); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
|
||||
using System.Xml.Serialization; |
||||
|
||||
namespace ErsatzTV.Infrastructure.Plex.Models; |
||||
|
||||
public class PlexCollectionResponse |
||||
{ |
||||
[XmlAttribute("id")] |
||||
public int Id { get; set; } |
||||
|
||||
[XmlAttribute("tag")] |
||||
public string Tag { get; set; } |
||||
} |
||||
@ -0,0 +1,244 @@
@@ -0,0 +1,244 @@
|
||||
using System.Security.Cryptography; |
||||
using ErsatzTV.Infrastructure.Plex.Models; |
||||
|
||||
namespace ErsatzTV.Infrastructure.Plex; |
||||
|
||||
public static class PlexEtag |
||||
{ |
||||
public static string ForMovie(PlexMetadataResponse response) |
||||
{ |
||||
using var ms = new MemoryStream(); |
||||
using var bw = new BinaryWriter(ms); |
||||
|
||||
// video key
|
||||
bw.Write(response.Key); |
||||
|
||||
// video added at
|
||||
bw.Write(response.AddedAt); |
||||
|
||||
// video updated at
|
||||
bw.Write(response.UpdatedAt); |
||||
|
||||
foreach (PlexMediaResponse<PlexPartResponse> media in response.Media) |
||||
{ |
||||
// media id
|
||||
bw.Write((byte)FieldKey.MediaId); |
||||
bw.Write(media.Id); |
||||
|
||||
// media part id
|
||||
foreach (PlexPartResponse part in media.Part) |
||||
{ |
||||
bw.Write((byte)FieldKey.PartId); |
||||
bw.Write(part.Id); |
||||
} |
||||
} |
||||
|
||||
// genre ids
|
||||
foreach (PlexGenreResponse genre in Optional(response.Genre).Flatten()) |
||||
{ |
||||
bw.Write((byte)FieldKey.GenreTag); |
||||
bw.Write(genre.Tag); |
||||
} |
||||
|
||||
// director ids
|
||||
foreach (PlexDirectorResponse director in Optional(response.Director).Flatten()) |
||||
{ |
||||
bw.Write((byte)FieldKey.DirectorTag); |
||||
bw.Write(director.Tag); |
||||
} |
||||
|
||||
// writer ids
|
||||
foreach (PlexWriterResponse writer in Optional(response.Writer).Flatten()) |
||||
{ |
||||
bw.Write((byte)FieldKey.WriterTag); |
||||
bw.Write(writer.Tag); |
||||
} |
||||
|
||||
// collection ids
|
||||
foreach (PlexCollectionResponse collection in Optional(response.Collection).Flatten()) |
||||
{ |
||||
bw.Write((byte)FieldKey.CollectionTag); |
||||
bw.Write(collection.Tag); |
||||
} |
||||
|
||||
// role ids
|
||||
foreach (PlexRoleResponse role in Optional(response.Role).Flatten()) |
||||
{ |
||||
bw.Write((byte)FieldKey.RoleTag); |
||||
bw.Write(role.Tag); |
||||
} |
||||
|
||||
ms.Position = 0; |
||||
byte[] hash = SHA1.Create().ComputeHash(ms); |
||||
return BitConverter.ToString(hash).Replace("-", string.Empty); |
||||
} |
||||
|
||||
public static string ForShow(PlexMetadataResponse response) |
||||
{ |
||||
using var ms = new MemoryStream(); |
||||
using var bw = new BinaryWriter(ms); |
||||
|
||||
// video key
|
||||
bw.Write(response.Key); |
||||
|
||||
// video added at
|
||||
bw.Write(response.AddedAt); |
||||
|
||||
// video updated at
|
||||
bw.Write(response.UpdatedAt); |
||||
|
||||
// genre ids
|
||||
foreach (PlexGenreResponse genre in Optional(response.Genre).Flatten()) |
||||
{ |
||||
bw.Write((byte)FieldKey.GenreTag); |
||||
bw.Write(genre.Tag); |
||||
} |
||||
|
||||
// collection ids
|
||||
foreach (PlexCollectionResponse collection in Optional(response.Collection).Flatten()) |
||||
{ |
||||
bw.Write((byte)FieldKey.CollectionTag); |
||||
bw.Write(collection.Tag); |
||||
} |
||||
|
||||
// role ids
|
||||
foreach (PlexRoleResponse role in Optional(response.Role).Flatten()) |
||||
{ |
||||
bw.Write((byte)FieldKey.RoleTag); |
||||
bw.Write(role.Tag); |
||||
} |
||||
|
||||
ms.Position = 0; |
||||
byte[] hash = SHA1.Create().ComputeHash(ms); |
||||
return BitConverter.ToString(hash).Replace("-", string.Empty); |
||||
} |
||||
|
||||
public static string ForSeason(PlexXmlMetadataResponse response) |
||||
{ |
||||
using var ms = new MemoryStream(); |
||||
using var bw = new BinaryWriter(ms); |
||||
|
||||
// video key
|
||||
bw.Write(response.Key); |
||||
|
||||
// video added at
|
||||
bw.Write(response.AddedAt); |
||||
|
||||
// video updated at
|
||||
bw.Write(response.UpdatedAt); |
||||
|
||||
// collection ids
|
||||
foreach (PlexCollectionResponse collection in Optional(response.Collection).Flatten()) |
||||
{ |
||||
bw.Write((byte)FieldKey.CollectionTag); |
||||
bw.Write(collection.Tag); |
||||
} |
||||
|
||||
// thumb
|
||||
if (!string.IsNullOrWhiteSpace(response.Thumb)) |
||||
{ |
||||
bw.Write(response.Thumb); |
||||
} |
||||
|
||||
// art
|
||||
if (!string.IsNullOrWhiteSpace(response.Art)) |
||||
{ |
||||
bw.Write(response.Art); |
||||
} |
||||
|
||||
ms.Position = 0; |
||||
byte[] hash = SHA1.Create().ComputeHash(ms); |
||||
return BitConverter.ToString(hash).Replace("-", string.Empty); |
||||
} |
||||
|
||||
public static string ForEpisode(PlexXmlMetadataResponse response) |
||||
{ |
||||
using var ms = new MemoryStream(); |
||||
using var bw = new BinaryWriter(ms); |
||||
|
||||
// video key
|
||||
bw.Write(response.Key); |
||||
|
||||
// video added at
|
||||
bw.Write(response.AddedAt); |
||||
|
||||
// video updated at
|
||||
bw.Write(response.UpdatedAt); |
||||
|
||||
foreach (PlexMediaResponse<PlexXmlPartResponse> media in response.Media) |
||||
{ |
||||
// media id
|
||||
bw.Write((byte)FieldKey.MediaId); |
||||
bw.Write(media.Id); |
||||
|
||||
// media part id
|
||||
foreach (PlexXmlPartResponse part in media.Part) |
||||
{ |
||||
bw.Write((byte)FieldKey.PartId); |
||||
bw.Write(part.Id); |
||||
|
||||
// media part id
|
||||
foreach (PlexStreamResponse stream in part.Stream) |
||||
{ |
||||
bw.Write((byte)FieldKey.StreamId); |
||||
bw.Write(stream.Id); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// genre ids
|
||||
foreach (PlexGenreResponse genre in Optional(response.Genre).Flatten()) |
||||
{ |
||||
bw.Write((byte)FieldKey.GenreTag); |
||||
bw.Write(genre.Tag); |
||||
} |
||||
|
||||
// director ids
|
||||
foreach (PlexDirectorResponse director in Optional(response.Director).Flatten()) |
||||
{ |
||||
bw.Write((byte)FieldKey.DirectorTag); |
||||
bw.Write(director.Tag); |
||||
} |
||||
|
||||
// writer ids
|
||||
foreach (PlexWriterResponse writer in Optional(response.Writer).Flatten()) |
||||
{ |
||||
bw.Write((byte)FieldKey.WriterTag); |
||||
bw.Write(writer.Tag); |
||||
} |
||||
|
||||
// collection ids
|
||||
foreach (PlexCollectionResponse collection in Optional(response.Collection).Flatten()) |
||||
{ |
||||
bw.Write((byte)FieldKey.CollectionTag); |
||||
bw.Write(collection.Tag); |
||||
} |
||||
|
||||
// role ids
|
||||
foreach (PlexRoleResponse role in Optional(response.Role).Flatten()) |
||||
{ |
||||
bw.Write((byte)FieldKey.RoleTag); |
||||
bw.Write(role.Tag); |
||||
} |
||||
|
||||
ms.Position = 0; |
||||
byte[] hash = SHA1.Create().ComputeHash(ms); |
||||
return BitConverter.ToString(hash).Replace("-", string.Empty); |
||||
} |
||||
|
||||
private enum FieldKey : byte |
||||
{ |
||||
MediaId = 0, |
||||
PartId = 1, |
||||
StreamId = 2, |
||||
|
||||
GenreTag = 10, |
||||
DirectorTag = 11, |
||||
WriterTag = 12, |
||||
CollectionTag = 13, |
||||
RoleTag = 14, |
||||
|
||||
Thumb = 20, |
||||
Art = 21 |
||||
} |
||||
} |
||||
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
#! /usr/bin/env bash |
||||
|
||||
cd "$(git rev-parse --show-cdup)" || exit |
||||
|
||||
dotnet tool restore |
||||
dotnet jb cleanupcode ErsatzTV.sln --exclude='CHANGELOG.md;scripts/**;generated/**;ErsatzTV/client-app/**' |
||||
Loading…
Reference in new issue