Merge pull request #42 from jellyfin/10.8

10.8 support
This commit is contained in:
Claus Vium 2021-11-01 22:21:25 +01:00 committed by GitHub
commit 6ed2b0ba34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 150 additions and 75 deletions

View File

@ -19,11 +19,14 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.x
dotnet-version: 6.0.x
include-prerelease: true
- name: Build Jellyfin Plugin
uses: oddstr13/jellyfin-plugin-repository-manager@v0.4.2
id: jprm
with:
dotnet-target: net6.0
- name: Upload Artifact
uses: actions/upload-artifact@v2

View File

@ -30,7 +30,8 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.x
dotnet-version: 6.0.x
include-prerelease: true
- name: Initialize CodeQL
uses: github/codeql-action/init@v1

21
.github/workflows/command-dispatch.yaml vendored Normal file
View File

@ -0,0 +1,21 @@
# Allows for the definition of PR and Issue /commands
name: Slash Command Dispatcher
on:
issue_comment:
types:
- created
jobs:
launcher:
runs-on: ubuntu-latest
steps:
- name: Command Dispatch
uses: peter-evans/slash-command-dispatch@v2
with:
token: ${{ secrets.JF_BOT_TOKEN }}
permission: write
issue-type: pull-request
commands: |-
rebase
update-prep

34
.github/workflows/command-rebase.yaml vendored Normal file
View File

@ -0,0 +1,34 @@
name: PR Rebase Command
on:
repository_dispatch:
types:
- rebase-command
jobs:
rebase:
runs-on: ubuntu-latest
steps:
- name: Rebase PR
uses: peter-evans/rebase@v1
id: rebase
with:
head: ${{ github.event.client_payload.pull_request.head.label }}
- name: Add Success Reaction
if: ${{ steps.rebase.outputs.rebased-count == 1 }}
uses: peter-evans/create-or-update-comment@v1
with:
token: ${{ secrets.JF_BOT_TOKEN }}
repository: ${{ github.event.client_payload.github.payload.repository.full_name }}
comment-id: ${{ github.event.client_payload.github.payload.comment.id }}
reaction-type: hooray
- name: Add Failure Reaction
if: ${{ steps.rebase.outputs.rebased-count == 0 || failure() }}
uses: peter-evans/create-or-update-comment@v1
with:
token: ${{ secrets.JF_BOT_TOKEN }}
repository: ${{ github.event.client_payload.github.payload.repository.full_name }}
comment-id: ${{ github.event.client_payload.github.payload.comment.id }}
reaction-type: confused, -1

View File

@ -19,7 +19,8 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.x
dotnet-version: 6.0.x
include-prerelease: true
- name: Install dependencies
run: dotnet restore

View File

@ -1,11 +1,16 @@
# Automates creation of Release Drafts using Release Drafter
name: Update Release Draft
name: Update Release Draft & Create Release Bump PR
on:
push:
branches:
- master
paths-ignore:
- build.yaml
workflow_dispatch:
repository_dispatch:
types:
- update-prep-command
jobs:
update_release_draft:
@ -23,9 +28,9 @@ jobs:
- name: Setup YQ
uses: chrisdickinson/setup-yq@latest
with:
yq-version: v4.9.6
yq-version: v4.12.2
- name: Parse changelog
- name: Set-up Environment
run: |
TAG="${{ steps.draft.outputs.tag_name }}"
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
@ -41,16 +46,22 @@ jobs:
cat cl.md >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
echo "HAS_CHANGES=$(grep -qie 'No changes$' cl.md && echo false || echo true)" >> $GITHUB_ENV
rm cl.md
- name: Checkout repository
echo "ABI_VERSION=$(curl -s https://api.jellyfin.org/openapi/jellyfin-openapi-stable.json | jq -r '.info.version').0" >> $GITHUB_ENV
- name: Checkout Repository
if: ${{ env.HAS_CHANGES == 'true' }}
uses: actions/checkout@v2
- name: Update build.yaml
if: ${{ env.HAS_CHANGES == 'true' }}
run: |
yq eval '.version = env(VERSION) | .changelog = strenv(CHANGELOG) | .changelog style="literal"' -i build.yaml
yq eval '.version = env(VERSION) | .targetAbi = env(ABI_VERSION) | .changelog = strenv(CHANGELOG) | .changelog style="literal"' -i build.yaml
- name: Commit Changes
if: ${{ env.HAS_CHANGES == 'true' }}
run: |
git config user.name "jellyfin-bot"
git config user.email "team@jellyfin.org"
@ -59,6 +70,7 @@ jobs:
git push -f origin prepare-${{ env.VERSION }}
- name: Create or Update PR
if: ${{ env.HAS_CHANGES == 'true' }}
uses: k3rnels-actions/pr-update@v1
with:
token: ${{ secrets.JF_BOT_TOKEN }}

View File

@ -10,12 +10,12 @@ namespace TVHeadEnd.DataHelper
{
public class AutorecDataHelper
{
private readonly ILogger<LiveTvService> _logger;
private readonly ILogger<AutorecDataHelper> _logger;
private readonly Dictionary<string, HTSMessage> _data;
private readonly DateTime _initialDateTimeUTC = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public AutorecDataHelper(ILogger<LiveTvService> logger)
public AutorecDataHelper(ILogger<AutorecDataHelper> logger)
{
_logger = logger;
_data = new Dictionary<string, HTSMessage>();

View File

@ -12,13 +12,13 @@ namespace TVHeadEnd.DataHelper
{
public class ChannelDataHelper
{
private readonly ILogger<LiveTvService> _logger;
private readonly ILogger<ChannelDataHelper> _logger;
private readonly TunerDataHelper _tunerDataHelper;
private readonly Dictionary<int, HTSMessage> _data;
private readonly Dictionary<string, string> _piconData;
private string _channelType4Other = "Ignore";
public ChannelDataHelper(ILogger<LiveTvService> logger, TunerDataHelper tunerDataHelper)
public ChannelDataHelper(ILogger<ChannelDataHelper> logger, TunerDataHelper tunerDataHelper)
{
_logger = logger;
_tunerDataHelper = tunerDataHelper;
@ -27,7 +27,7 @@ namespace TVHeadEnd.DataHelper
_piconData = new Dictionary<string, string>();
}
public ChannelDataHelper(ILogger<LiveTvService> logger) : this(logger, null) {}
public ChannelDataHelper(ILogger<ChannelDataHelper> logger) : this(logger, null) {}
public void SetChannelType4Other(string channelType4Other)
{

View File

@ -12,12 +12,12 @@ namespace TVHeadEnd.DataHelper
{
public class DvrDataHelper
{
private readonly ILogger<LiveTvService> _logger;
private readonly ILogger<DvrDataHelper> _logger;
private readonly Dictionary<string, HTSMessage> _data;
private readonly DateTime _initialDateTimeUTC = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public DvrDataHelper(ILogger<LiveTvService> logger)
public DvrDataHelper(ILogger<DvrDataHelper> logger)
{
_logger = logger;
_data = new Dictionary<string, HTSMessage>();

View File

@ -2,13 +2,17 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.LiveTv;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
using TVHeadEnd.DataHelper;
using TVHeadEnd.HTSP;
@ -22,7 +26,9 @@ namespace TVHeadEnd
private readonly object _lock = new Object();
private readonly ILogger<LiveTvService> _logger;
private readonly ILoggerFactory _loggerFactory;
private readonly ILogger<HTSConnectionHandler> _logger;
private readonly IHttpClientFactory _httpClientFactory;
private volatile Boolean _initialLoadFinished = false;
private volatile Boolean _connected = false;
@ -50,23 +56,25 @@ namespace TVHeadEnd
private Dictionary<string, string> _headers = new Dictionary<string, string>();
private HTSConnectionHandler(ILogger<LiveTvService> logger)
private HTSConnectionHandler(ILoggerFactory loggerFactory, IHttpClientFactory httpClientFactory)
{
_logger = logger;
_loggerFactory = loggerFactory;
_logger = loggerFactory.CreateLogger<HTSConnectionHandler>();
_httpClientFactory = httpClientFactory;
//System.Diagnostics.StackTrace t = new System.Diagnostics.StackTrace();
_logger.LogDebug("[TVHclient] HTSConnectionHandler");
_channelDataHelper = new ChannelDataHelper(logger);
_dvrDataHelper = new DvrDataHelper(logger);
_autorecDataHelper = new AutorecDataHelper(logger);
_channelDataHelper = new ChannelDataHelper(loggerFactory.CreateLogger<ChannelDataHelper>());
_dvrDataHelper = new DvrDataHelper(loggerFactory.CreateLogger<DvrDataHelper>());
_autorecDataHelper = new AutorecDataHelper(loggerFactory.CreateLogger<AutorecDataHelper>());
init();
_channelDataHelper.SetChannelType4Other(_channelType);
}
public static HTSConnectionHandler GetInstance(ILogger<LiveTvService> logger)
public static HTSConnectionHandler GetInstance(ILoggerFactory loggerFactory, IHttpClientFactory httpClientFactory)
{
if (_instance == null)
{
@ -74,7 +82,7 @@ namespace TVHeadEnd
{
if (_instance == null)
{
_instance = new HTSConnectionHandler(logger);
_instance = new HTSConnectionHandler(loggerFactory, httpClientFactory);
}
}
}
@ -166,7 +174,7 @@ namespace TVHeadEnd
_headers["Authorization"] = "Basic " + authInfo;
}
public ImageStream GetChannelImage(string channelId, CancellationToken cancellationToken)
public async Task<ImageStream> GetChannelImage(string channelId, CancellationToken cancellationToken)
{
try
{
@ -176,28 +184,30 @@ namespace TVHeadEnd
_logger.LogDebug("[TVHclient] HTSConnectionHandler.GetChannelImage: channelIcon: {ico}", channelIcon);
WebRequest request = null;
using var request = new HttpRequestMessage();
request.Method = HttpMethod.Get;
if (channelIcon.StartsWith("http"))
{
request = WebRequest.Create(channelIcon);
request.RequestUri = new Uri(channelIcon);
_logger.LogDebug("[TVHclient] HTSConnectionHandler.GetChannelImage: WebRequest: {ico}", channelIcon);
}
else
{
string requestStr = "http://" + _tvhServerName + ":" + _httpPort + _webRoot + "/" + channelIcon;
request = WebRequest.Create(requestStr);
request.Headers["Authorization"] = _headers["Authorization"];
request.RequestUri = new Uri(requestStr);
request.Headers.Authorization = AuthenticationHeaderValue.Parse(_headers[HeaderNames.Authorization]);
_logger.LogDebug("[TVHclient] HTSConnectionHandler.GetChannelImage: WebRequest: {req}", requestStr);
}
var responseMessage = await _httpClientFactory.CreateClient(NamedClient.Default)
.SendAsync(request, cancellationToken)
.ConfigureAwait(false);
responseMessage.EnsureSuccessStatusCode();
var stream = await responseMessage.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
HttpWebResponse httpWebReponse = (HttpWebResponse)request.GetResponse();
Stream stream = httpWebReponse.GetResponseStream();
ImageStream imageStream = new ImageStream();
ImageStream imageStream;
int lastDot = channelIcon.LastIndexOf('.');
if (lastDot > -1)
@ -210,31 +220,31 @@ namespace TVHeadEnd
switch (suffix)
{
case "bmp":
imageStream.Stream = stream;
imageStream = new ImageStream(stream);
imageStream.Format = MediaBrowser.Model.Drawing.ImageFormat.Bmp;
_logger.LogDebug("[TVHclient] HTSConnectionHandler.GetChannelImage: using fixed image type BMP");
break;
case "gif":
imageStream.Stream = stream;
imageStream = new ImageStream(stream);
imageStream.Format = MediaBrowser.Model.Drawing.ImageFormat.Gif;
_logger.LogDebug("[TVHclient] HTSConnectionHandler.GetChannelImage: using fixed image type GIF");
break;
case "jpg":
imageStream.Stream = stream;
imageStream = new ImageStream(stream);
imageStream.Format = MediaBrowser.Model.Drawing.ImageFormat.Jpg;
_logger.LogDebug("[TVHclient] HTSConnectionHandler.GetChannelImage: using fixed image type JPG");
break;
case "png":
imageStream.Stream = stream;
imageStream = new ImageStream(stream);
imageStream.Format = MediaBrowser.Model.Drawing.ImageFormat.Png;
_logger.LogDebug("[TVHclient] HTSConnectionHandler.GetChannelImage: using fixed image type PNG");
break;
case "webp":
imageStream.Stream = stream;
imageStream = new ImageStream(stream);
imageStream.Format = MediaBrowser.Model.Drawing.ImageFormat.Webp;
_logger.LogDebug("[TVHclient] HTSConnectionHandler.GetChannelImage: using fixed image type WEBP");
break;
@ -244,7 +254,7 @@ namespace TVHeadEnd
//Image image = Image.FromStream(stream);
//imageStream.Stream = ImageToPNGStream(image);
//imageStream.Format = MediaBrowser.Model.Drawing.ImageFormat.Png;
imageStream.Stream = stream;
imageStream = new ImageStream(stream);
imageStream.Format = MediaBrowser.Model.Drawing.ImageFormat.Png;
break;
}
@ -255,7 +265,7 @@ namespace TVHeadEnd
//Image image = Image.FromStream(stream);
//imageStream.Stream = ImageToPNGStream(image);
//imageStream.Format = MediaBrowser.Model.Drawing.ImageFormat.Png;
imageStream.Stream = stream;
imageStream = new ImageStream(stream);
imageStream.Format = MediaBrowser.Model.Drawing.ImageFormat.Png;
}
@ -309,7 +319,7 @@ namespace TVHeadEnd
{
_logger.LogDebug("[TVHclient] HTSConnectionHandler.ensureConnection: create new HTS connection");
Version version = Assembly.GetEntryAssembly().GetName().Version;
_htsConnection = new HTSConnectionAsync(this, "TVHclient4Emby-" + version.ToString(), "" + HTSMessage.HTSP_VERSION, _logger);
_htsConnection = new HTSConnectionAsync(this, "TVHclient4Emby-" + version.ToString(), "" + HTSMessage.HTSP_VERSION, _loggerFactory);
_connected = false;
}

View File

@ -22,7 +22,8 @@ namespace TVHeadEnd.HTSP
private readonly HTSConnectionListener _listener;
private readonly String _clientName;
private readonly String _clientVersion;
private readonly ILogger<LiveTvService> _logger;
private readonly ILoggerFactory _loggerFactory;
private readonly ILogger<HTSConnectionAsync> _logger;
private int _serverProtocolVersion;
private string _servername;
@ -46,9 +47,10 @@ namespace TVHeadEnd.HTSP
private Socket _socket = null;
public HTSConnectionAsync(HTSConnectionListener listener, String clientName, String clientVersion, ILogger<LiveTvService> logger)
public HTSConnectionAsync(HTSConnectionListener listener, String clientName, String clientVersion, ILoggerFactory loggerFactory)
{
_logger = logger;
_loggerFactory = loggerFactory;
_logger = loggerFactory.CreateLogger<HTSConnectionAsync>();
_connected = false;
_lock = new object();
@ -414,7 +416,7 @@ namespace TVHeadEnd.HTSP
byte[] lengthInformation = _buffer.getFromStart(4);
long messageDataLength = HTSMessage.uIntToLong(lengthInformation[0], lengthInformation[1], lengthInformation[2], lengthInformation[3]);
byte[] messageData = _buffer.extractFromStart((int)messageDataLength + 4); // should be long !!!
HTSMessage response = HTSMessage.parse(messageData, _logger);
HTSMessage response = HTSMessage.parse(messageData, _loggerFactory.CreateLogger<HTSMessage>());
_receivedMessagesQueue.Enqueue(response);
}
catch (Exception ex)

View File

@ -19,7 +19,7 @@ namespace TVHeadEnd.HTSP
private const byte HMF_LIST = 5;
private readonly Dictionary<string, object> _dict;
private ILogger<LiveTvService> _logger = null;
private ILogger<HTSMessage> _logger = null;
private byte[] _data = null;
public HTSMessage()
@ -383,7 +383,7 @@ namespace TVHeadEnd.HTSP
return b1;
}
public static HTSMessage parse(byte[] data, ILogger<LiveTvService> logger)
public static HTSMessage parse(byte[] data, ILogger<HTSMessage> logger)
{
if (data.Length < 4)
{

View File

@ -6,8 +6,7 @@ namespace TVHeadEnd.Helper
{
public static byte[] GenerateSaltedSHA1(string plainTextString, byte[] saltBytes)
{
HashAlgorithm algorithm = new SHA1Managed();
using HashAlgorithm algorithm = SHA1.Create();
byte[] plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainTextString);
byte[] plainTextWithSaltBytes = new byte[plainTextBytes.Length + saltBytes.Length];

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@ -37,14 +38,13 @@ namespace TVHeadEnd
private readonly ILogger<LiveTvService> _logger;
public DateTime LastRecordingChange = DateTime.MinValue;
public LiveTvService(ILogger<LiveTvService> logger, IMediaEncoder mediaEncoder)
public LiveTvService(ILoggerFactory loggerFactory, IMediaEncoder mediaEncoder, IHttpClientFactory httpClientFactory)
{
//System.Diagnostics.StackTrace t = new System.Diagnostics.StackTrace();
logger.LogDebug("[TVHclient] LiveTvService");
_logger = loggerFactory.CreateLogger<LiveTvService>();
_logger.LogDebug("[TVHclient] LiveTvService()");
_logger = logger;
_htsConnectionHandler = HTSConnectionHandler.GetInstance(_logger);
_htsConnectionHandler = HTSConnectionHandler.GetInstance(loggerFactory, httpClientFactory);
_htsConnectionHandler.setLiveTvService(this);
//Added for stream probing
@ -372,11 +372,6 @@ namespace TVHeadEnd
}
}
public Task<ImageStream> GetChannelImageAsync(string channelId, CancellationToken cancellationToken)
{
return Task.FromResult<ImageStream>(_htsConnectionHandler.GetChannelImage(channelId, cancellationToken));
}
public async Task<IEnumerable<ChannelInfo>> GetChannelsAsync(CancellationToken cancellationToken)
{
int timeOut = await WaitForInitialLoadTask(cancellationToken);

View File

@ -211,13 +211,11 @@ namespace TVHeadEnd
var service = GetService();
var allRecordings = await service.GetAllRecordingsAsync(cancellationToken).ConfigureAwait(false);
var result = new ChannelItemResult()
var result = new ChannelItemResult
{
Items = new List<ChannelItemInfo>()
Items = allRecordings.Where(filter).Select(info => ConvertToChannelItem(info)).ToList()
};
result.Items.AddRange(allRecordings.Where(filter).Select(ConvertToChannelItem));
return result;
}
@ -291,16 +289,14 @@ namespace TVHeadEnd
var service = GetService();
var allRecordings = await service.GetAllRecordingsAsync(cancellationToken).ConfigureAwait(false);
var result = new ChannelItemResult()
{
Items = new List<ChannelItemInfo>()
};
var result = new ChannelItemResult();
var items = new List<ChannelItemInfo>();
var series = allRecordings
.Where(i => i.IsSeries)
.ToLookup(i => i.Name, StringComparer.OrdinalIgnoreCase);
result.Items.AddRange(series.OrderBy(i => i.Key).Select(i => new ChannelItemInfo
items.AddRange(series.OrderBy(i => i.Key).Select(i => new ChannelItemInfo
{
Name = i.Key,
FolderType = ChannelFolderType.Container,
@ -313,7 +309,7 @@ namespace TVHeadEnd
if (kids != null)
{
result.Items.Add(new ChannelItemInfo
items.Add(new ChannelItemInfo
{
Name = "Kids",
FolderType = ChannelFolderType.Container,
@ -326,7 +322,7 @@ namespace TVHeadEnd
var movies = allRecordings.FirstOrDefault(i => i.IsMovie);
if (movies != null)
{
result.Items.Add(new ChannelItemInfo
items.Add(new ChannelItemInfo
{
Name = "Movies",
FolderType = ChannelFolderType.Container,
@ -339,7 +335,7 @@ namespace TVHeadEnd
var news = allRecordings.FirstOrDefault(i => i.IsNews);
if (news != null)
{
result.Items.Add(new ChannelItemInfo
items.Add(new ChannelItemInfo
{
Name = "News",
FolderType = ChannelFolderType.Container,
@ -352,7 +348,7 @@ namespace TVHeadEnd
var sports = allRecordings.FirstOrDefault(i => i.IsSports);
if (sports != null)
{
result.Items.Add(new ChannelItemInfo
items.Add(new ChannelItemInfo
{
Name = "Sports",
FolderType = ChannelFolderType.Container,
@ -365,7 +361,7 @@ namespace TVHeadEnd
var other = allRecordings.FirstOrDefault(i => !i.IsSports && !i.IsNews && !i.IsMovie && !i.IsKids && !i.IsSeries);
if (other != null)
{
result.Items.Add(new ChannelItemInfo
items.Add(new ChannelItemInfo
{
Name = "Others",
FolderType = ChannelFolderType.Container,
@ -375,6 +371,7 @@ namespace TVHeadEnd
});
}
result.Items = items;
return result;
}
}

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>9.0.0.0</AssemblyVersion>
<FileVersion>9.0.0.0</FileVersion>
</PropertyGroup>

View File

@ -3,7 +3,7 @@ guid: "3fd018e5-5e78-4e58-b280-a0c068febee0"
imageUrl: "https://repo.jellyfin.org/releases/plugin/images/jellyfin-plugin-tvheadend.png"
version: "9"
targetAbi: "10.7.0.0"
framework: "net5.0"
framework: "net6.0"
owner: "jellyfin"
overview: "Manage TVHeadend from Jellyfin"
description: "Manage TVHeadend from Jellyfin"