improve m3u channel list parsing

This commit is contained in:
Luke Pulverenti 2016-12-07 15:03:00 -05:00
parent 0130209cdc
commit 63a69cdc60
5 changed files with 81 additions and 62 deletions

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
@ -100,16 +101,23 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
extInf = extInf.Trim(); extInf = extInf.Trim();
channel.ImageUrl = FindProperty("tvg-logo", extInf); string remaining;
var attributes = ParseExtInf(extInf, out remaining);
extInf = remaining;
channel.Name = GetChannelName(extInf); string value;
if (attributes.TryGetValue("tvg-logo", out value))
{
channel.ImageUrl = value;
}
channel.Number = GetChannelNumber(extInf, mediaUrl); channel.Name = GetChannelName(extInf, attributes);
channel.Number = GetChannelNumber(extInf, attributes, mediaUrl);
return channel; return channel;
} }
private string GetChannelNumber(string extInf, string mediaUrl) private string GetChannelNumber(string extInf, Dictionary<string, string> attributes, string mediaUrl)
{ {
var nameParts = extInf.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var nameParts = extInf.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var nameInExtInf = nameParts.Length > 1 ? nameParts.Last().Trim() : null; var nameInExtInf = nameParts.Length > 1 ? nameParts.Last().Trim() : null;
@ -130,18 +138,41 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
} }
} }
if (string.IsNullOrWhiteSpace(numberString) || if (!string.IsNullOrWhiteSpace(numberString))
string.Equals(numberString, "-1", StringComparison.OrdinalIgnoreCase) ||
string.Equals(numberString, "0", StringComparison.OrdinalIgnoreCase))
{ {
numberString = FindProperty("tvg-id", extInf); numberString = numberString.Trim();
} }
if (string.IsNullOrWhiteSpace(numberString) || if (string.IsNullOrWhiteSpace(numberString) ||
string.Equals(numberString, "-1", StringComparison.OrdinalIgnoreCase) || string.Equals(numberString, "-1", StringComparison.OrdinalIgnoreCase) ||
string.Equals(numberString, "0", StringComparison.OrdinalIgnoreCase)) string.Equals(numberString, "0", StringComparison.OrdinalIgnoreCase))
{ {
numberString = FindProperty("channel-id", extInf); string value;
if (attributes.TryGetValue("tvg-id", out value))
{
numberString = value;
}
}
if (!string.IsNullOrWhiteSpace(numberString))
{
numberString = numberString.Trim();
}
if (string.IsNullOrWhiteSpace(numberString) ||
string.Equals(numberString, "-1", StringComparison.OrdinalIgnoreCase) ||
string.Equals(numberString, "0", StringComparison.OrdinalIgnoreCase))
{
string value;
if (attributes.TryGetValue("channel-id", out value))
{
numberString = value;
}
}
if (!string.IsNullOrWhiteSpace(numberString))
{
numberString = numberString.Trim();
} }
if (string.IsNullOrWhiteSpace(numberString) || if (string.IsNullOrWhiteSpace(numberString) ||
@ -160,13 +191,19 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
else else
{ {
numberString = Path.GetFileNameWithoutExtension(mediaUrl.Split('/').Last()); numberString = Path.GetFileNameWithoutExtension(mediaUrl.Split('/').Last());
double value;
if (!double.TryParse(numberString, NumberStyles.Any, CultureInfo.InvariantCulture, out value))
{
numberString = null;
}
} }
} }
return numberString; return numberString;
} }
private string GetChannelName(string extInf) private string GetChannelName(string extInf, Dictionary<string, string> attributes)
{ {
var nameParts = extInf.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var nameParts = extInf.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var nameInExtInf = nameParts.Length > 1 ? nameParts.Last().Trim() : null; var nameInExtInf = nameParts.Length > 1 ? nameParts.Last().Trim() : null;
@ -186,7 +223,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
} }
} }
var name = FindProperty("tvg-name", extInf); string name;
attributes.TryGetValue("tvg-name", out name);
if (string.IsNullOrWhiteSpace(name)) if (string.IsNullOrWhiteSpace(name))
{ {
name = nameInExtInf; name = nameInExtInf;
@ -194,7 +233,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
if (string.IsNullOrWhiteSpace(name)) if (string.IsNullOrWhiteSpace(name))
{ {
name = FindProperty("tvg-id", extInf); attributes.TryGetValue("tvg-id", out name);
} }
if (string.IsNullOrWhiteSpace(name)) if (string.IsNullOrWhiteSpace(name))
@ -205,18 +244,27 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
return name; return name;
} }
private string FindProperty(string property, string properties) private Dictionary<string, string> ParseExtInf(string line, out string remaining)
{ {
var dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
var reg = new Regex(@"([a-z0-9\-_]+)=\""([^""]+)\""", RegexOptions.IgnoreCase); var reg = new Regex(@"([a-z0-9\-_]+)=\""([^""]+)\""", RegexOptions.IgnoreCase);
var matches = reg.Matches(properties); var matches = reg.Matches(line);
var minIndex = int.MaxValue;
foreach (Match match in matches) foreach (Match match in matches)
{ {
if (match.Groups[1].Value == property) dict[match.Groups[1].Value] = match.Groups[2].Value;
{ minIndex = Math.Min(minIndex, match.Index);
return match.Groups[2].Value;
}
} }
return null;
if (minIndex > 0 && minIndex < line.Length)
{
line = line.Substring(0, minIndex);
}
remaining = line;
return dict;
} }
} }

View File

@ -3,7 +3,6 @@ namespace MediaBrowser.Api.Reports
public enum ReportViewType public enum ReportViewType
{ {
ReportData, ReportData,
ReportStatistics,
ReportActivities ReportActivities
} }

View File

@ -60,7 +60,7 @@ namespace MediaBrowser.Api.Reports
{ {
/// <summary> Gets or sets the report view. </summary> /// <summary> Gets or sets the report view. </summary>
/// <value> The report view. </value> /// <value> The report view. </value>
[ApiMember(Name = "ReportView", Description = "The report view. Values (ReportData, ReportStatistics, ReportActivities)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "ReportView", Description = "The report view. Values (ReportData, ReportActivities)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public string ReportView { get; set; } public string ReportView { get; set; }
/// <summary> Gets or sets the report view. </summary> /// <summary> Gets or sets the report view. </summary>
@ -101,7 +101,7 @@ namespace MediaBrowser.Api.Reports
{ {
/// <summary> Gets or sets the report view. </summary> /// <summary> Gets or sets the report view. </summary>
/// <value> The report view. </value> /// <value> The report view. </value>
[ApiMember(Name = "ReportView", Description = "The report view. Values (ReportData, ReportStatistics, ReportActivities)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "ReportView", Description = "The report view. Values (ReportData, ReportActivities)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public string ReportView { get; set; } public string ReportView { get; set; }
/// <summary> Gets or sets the report view. </summary> /// <summary> Gets or sets the report view. </summary>
@ -120,13 +120,6 @@ namespace MediaBrowser.Api.Reports
public string ReportColumns { get; set; } public string ReportColumns { get; set; }
} }
[Route("/Reports/Statistics", "GET", Summary = "Gets reports statistics based on library items")]
public class GetReportStatistics : BaseReportRequest, IReturn<ReportStatResult>
{
public int? TopItems { get; set; }
}
[Route("/Reports/Items/Download", "GET", Summary = "Downloads report")] [Route("/Reports/Items/Download", "GET", Summary = "Downloads report")]
public class GetReportDownload : BaseReportRequest, IReportsDownload public class GetReportDownload : BaseReportRequest, IReportsDownload
{ {
@ -150,7 +143,7 @@ namespace MediaBrowser.Api.Reports
{ {
/// <summary> Gets or sets the report view. </summary> /// <summary> Gets or sets the report view. </summary>
/// <value> The report view. </value> /// <value> The report view. </value>
[ApiMember(Name = "ReportView", Description = "The report view. Values (ReportData, ReportStatistics, ReportActivities)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "ReportView", Description = "The report view. Values (ReportData, ReportActivities)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public string ReportView { get; set; } public string ReportView { get; set; }
/// <summary> Gets or sets the report view. </summary> /// <summary> Gets or sets the report view. </summary>

View File

@ -82,8 +82,6 @@ namespace MediaBrowser.Api.Reports
ReportBuilder dataBuilder = new ReportBuilder(_libraryManager); ReportBuilder dataBuilder = new ReportBuilder(_libraryManager);
result = dataBuilder.GetHeaders(request); result = dataBuilder.GetHeaders(request);
break; break;
case ReportViewType.ReportStatistics:
break;
case ReportViewType.ReportActivities: case ReportViewType.ReportActivities:
ReportActivitiesBuilder activityBuilder = new ReportActivitiesBuilder(_libraryManager, _userManager); ReportActivitiesBuilder activityBuilder = new ReportActivitiesBuilder(_libraryManager, _userManager);
result = activityBuilder.GetHeaders(request); result = activityBuilder.GetHeaders(request);
@ -109,20 +107,6 @@ namespace MediaBrowser.Api.Reports
return ToOptimizedResult(reportResult); return ToOptimizedResult(reportResult);
} }
/// <summary> Gets the given request. </summary>
/// <param name="request"> The request. </param>
/// <returns> A Task&lt;object&gt; </returns>
public async Task<object> Get(GetReportStatistics request)
{
if (string.IsNullOrEmpty(request.IncludeItemTypes))
return null;
request.DisplayType = "Screen";
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
var reportResult = await GetReportStatistic(request, user);
return ToOptimizedResult(reportResult);
}
/// <summary> Gets the given request. </summary> /// <summary> Gets the given request. </summary>
/// <param name="request"> The request. </param> /// <param name="request"> The request. </param>
/// <returns> A Task&lt;object&gt; </returns> /// <returns> A Task&lt;object&gt; </returns>
@ -155,7 +139,6 @@ namespace MediaBrowser.Api.Reports
ReportResult result = null; ReportResult result = null;
switch (reportViewType) switch (reportViewType)
{ {
case ReportViewType.ReportStatistics:
case ReportViewType.ReportData: case ReportViewType.ReportData:
ReportIncludeItemTypes reportRowType = ReportHelper.GetRowType(request.IncludeItemTypes); ReportIncludeItemTypes reportRowType = ReportHelper.GetRowType(request.IncludeItemTypes);
ReportBuilder dataBuilder = new ReportBuilder(_libraryManager); ReportBuilder dataBuilder = new ReportBuilder(_libraryManager);
@ -463,20 +446,6 @@ namespace MediaBrowser.Api.Reports
return reportResult; return reportResult;
} }
/// <summary> Gets report statistic. </summary>
/// <param name="request"> The request. </param>
/// <returns> The report statistic. </returns>
private async Task<ReportStatResult> GetReportStatistic(GetReportStatistics request, User user)
{
ReportIncludeItemTypes reportRowType = ReportHelper.GetRowType(request.IncludeItemTypes);
QueryResult<BaseItem> queryResult = await GetQueryResult(request, user).ConfigureAwait(false);
ReportStatBuilder reportBuilder = new ReportStatBuilder(_libraryManager);
ReportStatResult reportResult = reportBuilder.GetResult(queryResult.Items, ReportHelper.GetRowType(request.IncludeItemTypes), request.TopItems ?? 5);
reportResult.TotalRecordCount = reportResult.Groups.Count();
return reportResult;
}
#endregion #endregion
} }

View File

@ -3,6 +3,7 @@ using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.Linq; using System.Linq;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
@ -185,6 +186,15 @@ namespace MediaBrowser.Controller.Entities.TV
public string FindSeasonName() public string FindSeasonName()
{ {
var season = Season; var season = Season;
if (season == null)
{
if (ParentIndexNumber.HasValue)
{
return "Season " + ParentIndexNumber.Value.ToString(CultureInfo.InvariantCulture);
}
}
return season == null ? SeasonName : season.Name; return season == null ? SeasonName : season.Name;
} }