add basic open subtitle configuration
This commit is contained in:
parent
0d025f7fb6
commit
9e4b34a4b1
|
@ -131,17 +131,17 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||||
{
|
{
|
||||||
var args = "-vcodec " + codec;
|
var args = "-vcodec " + codec;
|
||||||
|
|
||||||
|
if (state.EnableMpegtsM2TsMode)
|
||||||
|
{
|
||||||
|
args += " -mpegts_m2ts_mode 1";
|
||||||
|
}
|
||||||
|
|
||||||
// See if we can save come cpu cycles by avoiding encoding
|
// See if we can save come cpu cycles by avoiding encoding
|
||||||
if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase))
|
if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return state.VideoStream != null && IsH264(state.VideoStream) ? args + " -bsf h264_mp4toannexb" : args;
|
return state.VideoStream != null && IsH264(state.VideoStream) ? args + " -bsf h264_mp4toannexb" : args;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.EnableMpegtsM2TsMode)
|
|
||||||
{
|
|
||||||
args += " -mpegts_m2ts_mode 1";
|
|
||||||
}
|
|
||||||
|
|
||||||
const string keyFrameArg = " -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+5))";
|
const string keyFrameArg = " -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+5))";
|
||||||
|
|
||||||
args += keyFrameArg;
|
args += keyFrameArg;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using MediaBrowser.Common.Events;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Configuration
|
namespace MediaBrowser.Controller.Configuration
|
||||||
{
|
{
|
||||||
|
@ -8,6 +10,11 @@ namespace MediaBrowser.Controller.Configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IServerConfigurationManager : IConfigurationManager
|
public interface IServerConfigurationManager : IConfigurationManager
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when [configuration updating].
|
||||||
|
/// </summary>
|
||||||
|
event EventHandler<GenericEventArgs<ServerConfiguration>> ConfigurationUpdating;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the application paths.
|
/// Gets the application paths.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -191,6 +191,7 @@
|
||||||
<Compile Include="Providers\IMetadataProvider.cs" />
|
<Compile Include="Providers\IMetadataProvider.cs" />
|
||||||
<Compile Include="Providers\IMetadataService.cs" />
|
<Compile Include="Providers\IMetadataService.cs" />
|
||||||
<Compile Include="Providers\IRemoteMetadataProvider.cs" />
|
<Compile Include="Providers\IRemoteMetadataProvider.cs" />
|
||||||
|
<Compile Include="Security\IEncryptionManager.cs" />
|
||||||
<Compile Include="Subtitles\ISubtitleManager.cs" />
|
<Compile Include="Subtitles\ISubtitleManager.cs" />
|
||||||
<Compile Include="Subtitles\ISubtitleProvider.cs" />
|
<Compile Include="Subtitles\ISubtitleProvider.cs" />
|
||||||
<Compile Include="Providers\ItemLookupInfo.cs" />
|
<Compile Include="Providers\ItemLookupInfo.cs" />
|
||||||
|
|
20
MediaBrowser.Controller/Security/IEncryptionManager.cs
Normal file
20
MediaBrowser.Controller/Security/IEncryptionManager.cs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.Security
|
||||||
|
{
|
||||||
|
public interface IEncryptionManager
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Encrypts the string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value.</param>
|
||||||
|
/// <returns>System.String.</returns>
|
||||||
|
string EncryptString(string value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decrypts the string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value.</param>
|
||||||
|
/// <returns>System.String.</returns>
|
||||||
|
string DecryptString(string value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -323,6 +323,9 @@ namespace MediaBrowser.Model.Configuration
|
||||||
public bool DownloadMovieSubtitles { get; set; }
|
public bool DownloadMovieSubtitles { get; set; }
|
||||||
public bool DownloadEpisodeSubtitles { get; set; }
|
public bool DownloadEpisodeSubtitles { get; set; }
|
||||||
|
|
||||||
|
public string OpenSubtitlesUsername { get; set; }
|
||||||
|
public string OpenSubtitlesPasswordHash { get; set; }
|
||||||
|
|
||||||
public SubtitleOptions()
|
public SubtitleOptions()
|
||||||
{
|
{
|
||||||
SubtitleDownloadLanguages = new string[] { };
|
SubtitleDownloadLanguages = new string[] { };
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Events;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Controller.Security;
|
||||||
using MediaBrowser.Controller.Subtitles;
|
using MediaBrowser.Controller.Subtitles;
|
||||||
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Providers;
|
using MediaBrowser.Model.Providers;
|
||||||
|
@ -16,16 +18,52 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Providers.Subtitles
|
namespace MediaBrowser.Providers.Subtitles
|
||||||
{
|
{
|
||||||
public class OpenSubtitleDownloader : ISubtitleProvider
|
public class OpenSubtitleDownloader : ISubtitleProvider, IDisposable
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
||||||
|
|
||||||
public OpenSubtitleDownloader(ILogManager logManager, IHttpClient httpClient)
|
private readonly IServerConfigurationManager _config;
|
||||||
|
private readonly IEncryptionManager _encryption;
|
||||||
|
|
||||||
|
public OpenSubtitleDownloader(ILogManager logManager, IHttpClient httpClient, IServerConfigurationManager config, IEncryptionManager encryption)
|
||||||
{
|
{
|
||||||
_logger = logManager.GetLogger(GetType().Name);
|
_logger = logManager.GetLogger(GetType().Name);
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
|
_config = config;
|
||||||
|
_encryption = encryption;
|
||||||
|
|
||||||
|
_config.ConfigurationUpdating += _config_ConfigurationUpdating;
|
||||||
|
}
|
||||||
|
|
||||||
|
private const string PasswordHashPrefix = "h:";
|
||||||
|
void _config_ConfigurationUpdating(object sender, GenericEventArgs<ServerConfiguration> e)
|
||||||
|
{
|
||||||
|
var options = e.Argument.SubtitleOptions;
|
||||||
|
|
||||||
|
if (options != null &&
|
||||||
|
!string.IsNullOrWhiteSpace(options.OpenSubtitlesPasswordHash) &&
|
||||||
|
!options.OpenSubtitlesPasswordHash.StartsWith(PasswordHashPrefix, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
options.OpenSubtitlesPasswordHash = EncryptPassword(options.OpenSubtitlesPasswordHash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string EncryptPassword(string password)
|
||||||
|
{
|
||||||
|
return PasswordHashPrefix + _encryption.EncryptString(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string DecryptPassword(string password)
|
||||||
|
{
|
||||||
|
if (password == null ||
|
||||||
|
!password.StartsWith(PasswordHashPrefix, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _encryption.DecryptString(password.Substring(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
|
@ -35,7 +73,16 @@ namespace MediaBrowser.Providers.Subtitles
|
||||||
|
|
||||||
public IEnumerable<SubtitleMediaType> SupportedMediaTypes
|
public IEnumerable<SubtitleMediaType> SupportedMediaTypes
|
||||||
{
|
{
|
||||||
get { return new[] { SubtitleMediaType.Episode, SubtitleMediaType.Movie }; }
|
get
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(_config.Configuration.SubtitleOptions.OpenSubtitlesUsername) ||
|
||||||
|
string.IsNullOrWhiteSpace(_config.Configuration.SubtitleOptions.OpenSubtitlesPasswordHash))
|
||||||
|
{
|
||||||
|
return new SubtitleMediaType[] { };
|
||||||
|
}
|
||||||
|
|
||||||
|
return new[] { SubtitleMediaType.Episode, SubtitleMediaType.Movie };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<SubtitleResponse> GetSubtitles(string id, CancellationToken cancellationToken)
|
public Task<SubtitleResponse> GetSubtitles(string id, CancellationToken cancellationToken)
|
||||||
|
@ -59,7 +106,10 @@ namespace MediaBrowser.Providers.Subtitles
|
||||||
|
|
||||||
var downloadsList = new[] { int.Parse(ossId, _usCulture) };
|
var downloadsList = new[] { int.Parse(ossId, _usCulture) };
|
||||||
|
|
||||||
var resultDownLoad = OpenSubtitles.DownloadSubtitles(downloadsList);
|
await Login(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var resultDownLoad = await OpenSubtitles.DownloadSubtitlesAsync(downloadsList, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (!(resultDownLoad is MethodResponseSubtitleDownload))
|
if (!(resultDownLoad is MethodResponseSubtitleDownload))
|
||||||
{
|
{
|
||||||
throw new ApplicationException("Invalid response type");
|
throw new ApplicationException("Invalid response type");
|
||||||
|
@ -77,6 +127,21 @@ namespace MediaBrowser.Providers.Subtitles
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task Login(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var options = _config.Configuration.SubtitleOptions ?? new SubtitleOptions();
|
||||||
|
|
||||||
|
var user = options.OpenSubtitlesUsername ?? string.Empty;
|
||||||
|
var password = DecryptPassword(options.OpenSubtitlesPasswordHash);
|
||||||
|
|
||||||
|
var loginResponse = await OpenSubtitles.LogInAsync(user, password, "en", cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (!(loginResponse is MethodResponseLogIn))
|
||||||
|
{
|
||||||
|
throw new UnauthorizedAccessException("Authentication to OpenSubtitles failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<RemoteSubtitleInfo>> SearchSubtitles(SubtitleSearchRequest request, CancellationToken cancellationToken)
|
public async Task<IEnumerable<RemoteSubtitleInfo>> SearchSubtitles(SubtitleSearchRequest request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var imdbIdText = request.GetProviderId(MetadataProviders.Imdb);
|
var imdbIdText = request.GetProviderId(MetadataProviders.Imdb);
|
||||||
|
@ -116,13 +181,7 @@ namespace MediaBrowser.Providers.Subtitles
|
||||||
Utilities.HttpClient = _httpClient;
|
Utilities.HttpClient = _httpClient;
|
||||||
OpenSubtitles.SetUserAgent("OS Test User Agent");
|
OpenSubtitles.SetUserAgent("OS Test User Agent");
|
||||||
|
|
||||||
var loginResponse = await OpenSubtitles.LogInAsync("", "", "en", cancellationToken).ConfigureAwait(false);
|
await Login(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (!(loginResponse is MethodResponseLogIn))
|
|
||||||
{
|
|
||||||
_logger.Debug("Login error");
|
|
||||||
return new List<RemoteSubtitleInfo>();
|
|
||||||
}
|
|
||||||
|
|
||||||
var subLanguageId = request.Language;
|
var subLanguageId = request.Language;
|
||||||
var hash = Utilities.ComputeHash(request.MediaPath);
|
var hash = Utilities.ComputeHash(request.MediaPath);
|
||||||
|
@ -178,5 +237,10 @@ namespace MediaBrowser.Providers.Subtitles
|
||||||
IsHashMatch = i.MovieHash == hasCopy
|
IsHashMatch = i.MovieHash == hasCopy
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_config.ConfigurationUpdating -= _config_ConfigurationUpdating;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using MediaBrowser.Common.Events;
|
||||||
using MediaBrowser.Common.Implementations.Configuration;
|
using MediaBrowser.Common.Implementations.Configuration;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
@ -29,6 +30,8 @@ namespace MediaBrowser.Server.Implementations.Configuration
|
||||||
UpdateMetadataPath();
|
UpdateMetadataPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public event EventHandler<GenericEventArgs<ServerConfiguration>> ConfigurationUpdating;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the type of the configuration.
|
/// Gets the type of the configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -73,8 +76,8 @@ namespace MediaBrowser.Server.Implementations.Configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void UpdateItemsByNamePath()
|
private void UpdateItemsByNamePath()
|
||||||
{
|
{
|
||||||
((ServerApplicationPaths) ApplicationPaths).ItemsByNamePath = string.IsNullOrEmpty(Configuration.ItemsByNamePath) ?
|
((ServerApplicationPaths)ApplicationPaths).ItemsByNamePath = string.IsNullOrEmpty(Configuration.ItemsByNamePath) ?
|
||||||
null :
|
null :
|
||||||
Configuration.ItemsByNamePath;
|
Configuration.ItemsByNamePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,13 +108,15 @@ namespace MediaBrowser.Server.Implementations.Configuration
|
||||||
/// <exception cref="System.IO.DirectoryNotFoundException"></exception>
|
/// <exception cref="System.IO.DirectoryNotFoundException"></exception>
|
||||||
public override void ReplaceConfiguration(BaseApplicationConfiguration newConfiguration)
|
public override void ReplaceConfiguration(BaseApplicationConfiguration newConfiguration)
|
||||||
{
|
{
|
||||||
var newConfig = (ServerConfiguration) newConfiguration;
|
var newConfig = (ServerConfiguration)newConfiguration;
|
||||||
|
|
||||||
ValidateItemByNamePath(newConfig);
|
ValidateItemByNamePath(newConfig);
|
||||||
ValidateTranscodingTempPath(newConfig);
|
ValidateTranscodingTempPath(newConfig);
|
||||||
ValidatePathSubstitutions(newConfig);
|
ValidatePathSubstitutions(newConfig);
|
||||||
ValidateMetadataPath(newConfig);
|
ValidateMetadataPath(newConfig);
|
||||||
|
|
||||||
|
EventHelper.FireEventIfNotNull(ConfigurationUpdating, this, new GenericEventArgs<ServerConfiguration> { Argument = newConfig }, Logger);
|
||||||
|
|
||||||
base.ReplaceConfiguration(newConfiguration);
|
base.ReplaceConfiguration(newConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
"PasswordResetConfirmation": "Are you sure you wish to reset the password?",
|
"PasswordResetConfirmation": "Are you sure you wish to reset the password?",
|
||||||
"PasswordSaved": "Password saved.",
|
"PasswordSaved": "Password saved.",
|
||||||
"PasswordMatchError": "Password and password confirmation must match.",
|
"PasswordMatchError": "Password and password confirmation must match.",
|
||||||
"OptionOff": "Off",
|
|
||||||
"OptionOn": "On",
|
|
||||||
"OptionRelease": "Official Release",
|
"OptionRelease": "Official Release",
|
||||||
"OptionBeta": "Beta",
|
"OptionBeta": "Beta",
|
||||||
"OptionDev": "Dev (Unstable)",
|
"OptionDev": "Dev (Unstable)",
|
||||||
|
|
|
@ -147,10 +147,8 @@
|
||||||
"ScheduledTasksTitle": "Scheduled Tasks",
|
"ScheduledTasksTitle": "Scheduled Tasks",
|
||||||
"TabMyPlugins": "My Plugins",
|
"TabMyPlugins": "My Plugins",
|
||||||
"TabCatalog": "Catalog",
|
"TabCatalog": "Catalog",
|
||||||
"TabUpdates": "Updates",
|
|
||||||
"PluginsTitle": "Plugins",
|
"PluginsTitle": "Plugins",
|
||||||
"HeaderAutomaticUpdates": "Automatic Updates",
|
"HeaderAutomaticUpdates": "Automatic Updates",
|
||||||
"HeaderUpdateLevel": "Update Level",
|
|
||||||
"HeaderNowPlaying": "Now Playing",
|
"HeaderNowPlaying": "Now Playing",
|
||||||
"HeaderLatestAlbums": "Latest Albums",
|
"HeaderLatestAlbums": "Latest Albums",
|
||||||
"HeaderLatestSongs": "Latest Songs",
|
"HeaderLatestSongs": "Latest Songs",
|
||||||
|
@ -706,5 +704,13 @@
|
||||||
"OptionEnableM2tsModeHelp": "Enable m2ts mode when encoding to mpegts.",
|
"OptionEnableM2tsModeHelp": "Enable m2ts mode when encoding to mpegts.",
|
||||||
"OptionEstimateContentLength": "Estimate content length when transcoding",
|
"OptionEstimateContentLength": "Estimate content length when transcoding",
|
||||||
"OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding",
|
"OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding",
|
||||||
"OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well."
|
"OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.",
|
||||||
|
"HeaderSubtitleDownloadingHelp": "Media Browser can inspect your video files for missing subtitles, and download them using a subtitle provider such as OpenSubtitles.org.",
|
||||||
|
"HeaderDownloadSubtitlesFor": "Download subtitles for:",
|
||||||
|
"LabelRequireExternalSubtitles": "Download even if the video already contains graphical subtitles",
|
||||||
|
"LabelRequireExternalSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
|
||||||
|
"TabSubtitles": "Subtitles",
|
||||||
|
"LabelOpenSubtitlesUsername": "Open Subtitles username:",
|
||||||
|
"LabelOpenSubtitlesPassword": "Open Subtitles password:",
|
||||||
|
"LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language."
|
||||||
}
|
}
|
|
@ -64,6 +64,7 @@
|
||||||
<Reference Include="System.Drawing" />
|
<Reference Include="System.Drawing" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Security" />
|
||||||
<Reference Include="System.Web" />
|
<Reference Include="System.Web" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<Reference Include="MoreLinq">
|
<Reference Include="MoreLinq">
|
||||||
|
@ -201,6 +202,7 @@
|
||||||
<Compile Include="ScheduledTasks\ChapterImagesTask.cs" />
|
<Compile Include="ScheduledTasks\ChapterImagesTask.cs" />
|
||||||
<Compile Include="ScheduledTasks\RefreshIntrosTask.cs" />
|
<Compile Include="ScheduledTasks\RefreshIntrosTask.cs" />
|
||||||
<Compile Include="ScheduledTasks\RefreshMediaLibraryTask.cs" />
|
<Compile Include="ScheduledTasks\RefreshMediaLibraryTask.cs" />
|
||||||
|
<Compile Include="Security\EncryptionManager.cs" />
|
||||||
<Compile Include="ServerApplicationPaths.cs" />
|
<Compile Include="ServerApplicationPaths.cs" />
|
||||||
<Compile Include="ServerManager\ServerManager.cs" />
|
<Compile Include="ServerManager\ServerManager.cs" />
|
||||||
<Compile Include="ServerManager\WebSocketConnection.cs" />
|
<Compile Include="ServerManager\WebSocketConnection.cs" />
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
using MediaBrowser.Controller.Security;
|
||||||
|
using System;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Server.Implementations.Security
|
||||||
|
{
|
||||||
|
public class EncryptionManager : IEncryptionManager
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Encrypts the string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value.</param>
|
||||||
|
/// <returns>System.String.</returns>
|
||||||
|
/// <exception cref="System.ArgumentNullException">value</exception>
|
||||||
|
public string EncryptString(string value)
|
||||||
|
{
|
||||||
|
if (value == null) throw new ArgumentNullException("value");
|
||||||
|
|
||||||
|
return Encoding.Default.GetString(ProtectedData.Protect(Encoding.Default.GetBytes(value), null, DataProtectionScope.LocalMachine));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decrypts the string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value.</param>
|
||||||
|
/// <returns>System.String.</returns>
|
||||||
|
/// <exception cref="System.ArgumentNullException">value</exception>
|
||||||
|
public string DecryptString(string value)
|
||||||
|
{
|
||||||
|
if (value == null) throw new ArgumentNullException("value");
|
||||||
|
|
||||||
|
return Encoding.Default.GetString(ProtectedData.Unprotect(Encoding.Default.GetBytes(value), null, DataProtectionScope.LocalMachine));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,6 +29,7 @@ using MediaBrowser.Controller.Persistence;
|
||||||
using MediaBrowser.Controller.Plugins;
|
using MediaBrowser.Controller.Plugins;
|
||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Controller.Resolvers;
|
using MediaBrowser.Controller.Resolvers;
|
||||||
|
using MediaBrowser.Controller.Security;
|
||||||
using MediaBrowser.Controller.Session;
|
using MediaBrowser.Controller.Session;
|
||||||
using MediaBrowser.Controller.Sorting;
|
using MediaBrowser.Controller.Sorting;
|
||||||
using MediaBrowser.Controller.Subtitles;
|
using MediaBrowser.Controller.Subtitles;
|
||||||
|
@ -61,6 +62,7 @@ using MediaBrowser.Server.Implementations.Localization;
|
||||||
using MediaBrowser.Server.Implementations.MediaEncoder;
|
using MediaBrowser.Server.Implementations.MediaEncoder;
|
||||||
using MediaBrowser.Server.Implementations.Notifications;
|
using MediaBrowser.Server.Implementations.Notifications;
|
||||||
using MediaBrowser.Server.Implementations.Persistence;
|
using MediaBrowser.Server.Implementations.Persistence;
|
||||||
|
using MediaBrowser.Server.Implementations.Security;
|
||||||
using MediaBrowser.Server.Implementations.ServerManager;
|
using MediaBrowser.Server.Implementations.ServerManager;
|
||||||
using MediaBrowser.Server.Implementations.Session;
|
using MediaBrowser.Server.Implementations.Session;
|
||||||
using MediaBrowser.Server.Implementations.Themes;
|
using MediaBrowser.Server.Implementations.Themes;
|
||||||
|
@ -533,6 +535,8 @@ namespace MediaBrowser.ServerApplication
|
||||||
NotificationManager = new NotificationManager(LogManager, UserManager, ServerConfigurationManager);
|
NotificationManager = new NotificationManager(LogManager, UserManager, ServerConfigurationManager);
|
||||||
RegisterSingleInstance(NotificationManager);
|
RegisterSingleInstance(NotificationManager);
|
||||||
|
|
||||||
|
RegisterSingleInstance<IEncryptionManager>(new EncryptionManager());
|
||||||
|
|
||||||
SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor);
|
SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor);
|
||||||
RegisterSingleInstance(SubtitleManager);
|
RegisterSingleInstance(SubtitleManager);
|
||||||
|
|
||||||
|
|
|
@ -585,6 +585,7 @@ namespace MediaBrowser.WebDashboard.Api
|
||||||
"medialibrarypage.js",
|
"medialibrarypage.js",
|
||||||
"metadataconfigurationpage.js",
|
"metadataconfigurationpage.js",
|
||||||
"metadataimagespage.js",
|
"metadataimagespage.js",
|
||||||
|
"metadatasubtitles.js",
|
||||||
"moviegenres.js",
|
"moviegenres.js",
|
||||||
"moviecollections.js",
|
"moviecollections.js",
|
||||||
"movies.js",
|
"movies.js",
|
||||||
|
@ -605,7 +606,6 @@ namespace MediaBrowser.WebDashboard.Api
|
||||||
"playlist.js",
|
"playlist.js",
|
||||||
"plugincatalogpage.js",
|
"plugincatalogpage.js",
|
||||||
"pluginspage.js",
|
"pluginspage.js",
|
||||||
"pluginupdatespage.js",
|
|
||||||
"remotecontrol.js",
|
"remotecontrol.js",
|
||||||
"scheduledtaskpage.js",
|
"scheduledtaskpage.js",
|
||||||
"scheduledtaskspage.js",
|
"scheduledtaskspage.js",
|
||||||
|
|
|
@ -328,6 +328,9 @@
|
||||||
<Content Include="dashboard-ui\livetvtimers.html">
|
<Content Include="dashboard-ui\livetvtimers.html">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="dashboard-ui\metadatasubtitles.html">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<Content Include="dashboard-ui\movieslatest.html">
|
<Content Include="dashboard-ui\movieslatest.html">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -658,6 +661,9 @@
|
||||||
<Content Include="dashboard-ui\scripts\mediaplayer-video.js">
|
<Content Include="dashboard-ui\scripts\mediaplayer-video.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="dashboard-ui\scripts\metadatasubtitles.js">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<Content Include="dashboard-ui\scripts\movieslatest.js">
|
<Content Include="dashboard-ui\scripts\movieslatest.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -1781,16 +1787,6 @@
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Content Include="dashboard-ui\pluginupdates.html">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Content Include="dashboard-ui\scripts\pluginupdatespage.js">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="dashboard-ui\addplugin.html">
|
<Content Include="dashboard-ui\addplugin.html">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
|
|
@ -551,6 +551,117 @@ namespace OpenSubtitlesHandler
|
||||||
}
|
}
|
||||||
return new MethodResponseError("Fail", "DownloadSubtitles call failed !");
|
return new MethodResponseError("Fail", "DownloadSubtitles call failed !");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<IMethodResponse> DownloadSubtitlesAsync(int[] subIDS, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (TOKEN == "")
|
||||||
|
{
|
||||||
|
OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
|
||||||
|
return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
|
||||||
|
}
|
||||||
|
if (subIDS == null)
|
||||||
|
{
|
||||||
|
OSHConsole.UpdateLine("No subtitle id passed !!", DebugCode.Error);
|
||||||
|
return new MethodResponseError("Fail", "No subtitle id passed"); ;
|
||||||
|
}
|
||||||
|
if (subIDS.Length == 0)
|
||||||
|
{
|
||||||
|
OSHConsole.UpdateLine("No subtitle id passed !!", DebugCode.Error);
|
||||||
|
return new MethodResponseError("Fail", "No subtitle id passed"); ;
|
||||||
|
}
|
||||||
|
// Method call ..
|
||||||
|
List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
|
||||||
|
// Add token param
|
||||||
|
parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
|
||||||
|
// Add subtitle search parameters. Each one will be like 'array' of structs.
|
||||||
|
XmlRpcValueArray array = new XmlRpcValueArray();
|
||||||
|
foreach (int id in subIDS)
|
||||||
|
{
|
||||||
|
array.Values.Add(new XmlRpcValueBasic(id, XmlRpcBasicValueType.Int));
|
||||||
|
}
|
||||||
|
// Add the array to the parameters
|
||||||
|
parms.Add(array);
|
||||||
|
// Call !
|
||||||
|
XmlRpcMethodCall call = new XmlRpcMethodCall("DownloadSubtitles", parms);
|
||||||
|
OSHConsole.WriteLine("Sending DownloadSubtitles request to the server ...", DebugCode.Good);
|
||||||
|
// Send the request to the server
|
||||||
|
|
||||||
|
var httpResponse = await Utilities.SendRequestAsync(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
string response = Utilities.GetStreamString(httpResponse);
|
||||||
|
if (!response.Contains("ERROR:"))
|
||||||
|
{
|
||||||
|
// No error occur, get and decode the response.
|
||||||
|
XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
|
||||||
|
if (calls.Length > 0)
|
||||||
|
{
|
||||||
|
if (calls[0].Parameters.Count > 0)
|
||||||
|
{
|
||||||
|
// We expect Struct of 3 members:
|
||||||
|
//* the first is status
|
||||||
|
//* the second is [array of structs, each one includes subtitle file].
|
||||||
|
//* the third is [double basic value] represent seconds token by server.
|
||||||
|
XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
|
||||||
|
// Create the response, we'll need it later
|
||||||
|
MethodResponseSubtitleDownload R = new MethodResponseSubtitleDownload();
|
||||||
|
|
||||||
|
// To make sure response is not currepted by server, do it in loop
|
||||||
|
foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
|
||||||
|
{
|
||||||
|
if (MEMBER.Name == "status")
|
||||||
|
{
|
||||||
|
R.Status = (string)MEMBER.Data.Data;
|
||||||
|
OSHConsole.WriteLine("Status= " + R.Status);
|
||||||
|
}
|
||||||
|
else if (MEMBER.Name == "seconds")
|
||||||
|
{
|
||||||
|
R.Seconds = (double)MEMBER.Data.Data;
|
||||||
|
OSHConsole.WriteLine("Seconds= " + R.Seconds);
|
||||||
|
}
|
||||||
|
else if (MEMBER.Name == "data")
|
||||||
|
{
|
||||||
|
if (MEMBER.Data is XmlRpcValueArray)
|
||||||
|
{
|
||||||
|
OSHConsole.WriteLine("Download results:");
|
||||||
|
XmlRpcValueArray rarray = (XmlRpcValueArray)MEMBER.Data;
|
||||||
|
foreach (IXmlRpcValue subStruct in rarray.Values)
|
||||||
|
{
|
||||||
|
if (subStruct == null) continue;
|
||||||
|
if (!(subStruct is XmlRpcValueStruct)) continue;
|
||||||
|
|
||||||
|
SubtitleDownloadResult result = new SubtitleDownloadResult();
|
||||||
|
foreach (XmlRpcStructMember submember in ((XmlRpcValueStruct)subStruct).Members)
|
||||||
|
{
|
||||||
|
// To avoid errors of arranged info or missing ones, let's do it with switch..
|
||||||
|
switch (submember.Name)
|
||||||
|
{
|
||||||
|
case "idsubtitlefile": result.IdSubtitleFile = (string)submember.Data.Data; break;
|
||||||
|
case "data": result.Data = (string)submember.Data.Data; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
R.Results.Add(result);
|
||||||
|
OSHConsole.WriteLine("> IDSubtilteFile= " + result.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else// Unknown data ?
|
||||||
|
{
|
||||||
|
OSHConsole.WriteLine("Data= " + MEMBER.Data.Data.ToString(), DebugCode.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Return the response to user !!
|
||||||
|
return R;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OSHConsole.WriteLine(response, DebugCode.Error);
|
||||||
|
return new MethodResponseError("Fail", response);
|
||||||
|
}
|
||||||
|
return new MethodResponseError("Fail", "DownloadSubtitles call failed !");
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns comments for subtitles
|
/// Returns comments for subtitles
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user