Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/202411 ffmpeg #1833

Open
wants to merge 84 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
31251c4
ffmpeg init
qdraw Nov 16, 2024
8700012
WIP
qdraw Nov 16, 2024
81ed601
add downloader
qdraw Nov 17, 2024
69028dc
#1833 download scripts
qdraw Nov 17, 2024
ae4ef7a
#1833 rename && add scripts
qdraw Nov 17, 2024
be49b90
#1833 compatiblity ffmpeg
qdraw Nov 17, 2024
5a02fb3
#1833 update script
qdraw Nov 17, 2024
3993b5e
#1833 add checks to avoid wrong downloads
qdraw Nov 17, 2024
1673b24
#1833 add debug
qdraw Nov 18, 2024
e524d1e
#1833 add debug
qdraw Nov 18, 2024
b0c3b48
#1833 work
qdraw Nov 18, 2024
c8983cd
#1833 reformat
qdraw Nov 18, 2024
4448b81
Merge branch 'master' into feature/202411_ffmpeg
qdraw Nov 18, 2024
a3784a1
Merge branch 'master' into feature/202411_ffmpeg
qdraw Nov 18, 2024
cfadfb3
#1833 ffmpeg index
qdraw Nov 18, 2024
12d71cd
Merge branch 'master' into feature/202411_ffmpeg
qdraw Nov 18, 2024
c679926
Merge branch 'master' into feature/202411_ffmpeg
qdraw Nov 18, 2024
c634559
#1833 current os implementenation
qdraw Nov 19, 2024
648ea20
#1833 removve
qdraw Nov 22, 2024
1fb64de
Merge commit '2494f77fb7b0823ac79922a6bd3b734d8ad64ce1' into feature/…
qdraw Nov 29, 2024
a47e20c
#1833 add wrapper
qdraw Dec 1, 2024
fa62e68
Merge branch 'master' into feature/202411_ffmpeg
qdraw Dec 3, 2024
5978ec9
#1833 add parsing data
qdraw Dec 3, 2024
f264f2b
Merge branch 'master' into feature/202411_ffmpeg
qdraw Dec 3, 2024
eb97643
code signing, http client extensions, xttr mac os, cleanup folders te…
qdraw Dec 8, 2024
4ae3e16
rename test folders && auto format
qdraw Dec 8, 2024
dcc9615
#1833 split code
qdraw Dec 8, 2024
d44fae6
#1833 add tests
qdraw Dec 8, 2024
3d4da56
#1833 fixes
qdraw Dec 8, 2024
7dd26d8
#1833 change check
qdraw Dec 9, 2024
45805db
#1833 add tests
qdraw Dec 9, 2024
46775f5
#1833 list files
qdraw Dec 9, 2024
365663d
#1833 add create dir
qdraw Dec 9, 2024
58821f1
#1833 toList
qdraw Dec 9, 2024
c0f1b07
#1833 contents
qdraw Dec 9, 2024
0e96ff1
#1833 move chmod to variable && add windows tests
qdraw Dec 9, 2024
4e11802
#1833 windows tests
qdraw Dec 9, 2024
0b0e0f4
#1833 add rename
qdraw Dec 9, 2024
fcff216
#1833 exists instead of any
qdraw Dec 9, 2024
777963a
#1833 path seperator
qdraw Dec 9, 2024
08338c7
#1833 update zip
qdraw Dec 9, 2024
cc3d0c3
#1833 debug
qdraw Dec 9, 2024
5ccd6f2
#1833 add tests
qdraw Dec 9, 2024
3ceb482
#1833 build error
qdraw Dec 9, 2024
b79ca83
#1833 hidden file
qdraw Dec 9, 2024
879358b
#1833 actual test on mac os
qdraw Dec 9, 2024
011ce76
#1833 no cleanup
qdraw Dec 9, 2024
eda1e39
#1833 add not found cases
qdraw Dec 9, 2024
e06a3cf
#1833 check
qdraw Dec 9, 2024
2415819
#1833 sonar feedback
qdraw Dec 9, 2024
5429de5
#1833 rename action
qdraw Dec 9, 2024
419ddd7
#1833 add not found test
qdraw Dec 9, 2024
a0dddba
#1833 add write file
qdraw Dec 9, 2024
c5ae755
#1833 windows exclusions
qdraw Dec 9, 2024
3d1d08e
#1833 add check for parent dir
qdraw Dec 9, 2024
d2cecda
#1833 exclude windows
qdraw Dec 9, 2024
4aba0a4
#1833 refactorings
qdraw Dec 10, 2024
4328ddf
#1833 ok
qdraw Dec 10, 2024
978ce3a
#1833 win32 errors
qdraw Dec 11, 2024
f87b956
#1833 add exampleData
qdraw Dec 11, 2024
949dfa8
Merge branch 'feature/202411_ffmpeg' of https://github.com/qdraw/star…
qdraw Dec 11, 2024
3cdb236
#1833 update test
qdraw Dec 11, 2024
2f8aa12
#1833 fix tests for windows
qdraw Dec 11, 2024
fe02d7a
#1833 fix for not created
qdraw Dec 11, 2024
7b18326
#1833 add check && add to file scoped
qdraw Dec 13, 2024
3fbc8b8
#1833 shell injection
qdraw Dec 13, 2024
4c0b040
#1833 tests
qdraw Dec 13, 2024
1d7463e
#1833 add tests
qdraw Dec 13, 2024
86a6d46
#1833 order
qdraw Dec 13, 2024
9a8c921
#1833 fix
qdraw Dec 13, 2024
d11bbfe
#1833 add arch to foldername
qdraw Dec 13, 2024
f24421e
#1833 fix __ domain
qdraw Dec 13, 2024
11be84f
#1833 test
qdraw Dec 13, 2024
3dd53a0
#1833 add test
qdraw Dec 13, 2024
ff75bd1
Merge branch 'master' into feature/202411_ffmpeg
qdraw Dec 18, 2024
0ae4786
#1833 add preflight
qdraw Dec 18, 2024
a95133b
#1833 windows fixxes
qdraw Dec 19, 2024
313fb30
#1833 add extra checks
qdraw Dec 19, 2024
29f1740
Merge branch 'master' into feature/202411_ffmpeg
qdraw Dec 19, 2024
19a1681
#1833 test
qdraw Dec 19, 2024
33a579f
#1833 add storage
qdraw Dec 19, 2024
11c78fe
#1833 windows
qdraw Dec 19, 2024
1186cba
Merge branch 'master' into feature/202411_ffmpeg
qdraw Dec 19, 2024
0921295
#1833 spacing
qdraw Dec 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions starsky/starsky.foundation.http/Interfaces/IHttpClientHelper.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;

namespace starsky.foundation.http.Interfaces
namespace starsky.foundation.http.Interfaces;

public interface IHttpClientHelper
{
public interface IHttpClientHelper
{
Task<bool> Download(string sourceHttpUrl, string fullLocalPath, int retryAfterInSeconds = 15);
Task<KeyValuePair<bool, string>> ReadString(string sourceHttpUrl);
Task<KeyValuePair<bool, string>> PostString(string sourceHttpUrl,
HttpContent? httpContent, bool verbose = true);
}
Task<bool> Download(Uri sourceUri, string fullLocalPath, int retryAfterInSeconds = 15);
Task<bool> Download(string sourceHttpUrl, string fullLocalPath, int retryAfterInSeconds = 15);
Task<KeyValuePair<bool, string>> ReadString(string sourceHttpUrl);
Task<KeyValuePair<bool, string>> ReadString(Uri sourceHttpUrl);

Task<KeyValuePair<bool, string>> PostString(string sourceHttpUrl,
HttpContent? httpContent, bool verbose = true);
}
301 changes: 161 additions & 140 deletions starsky/starsky.foundation.http/Services/HttpClientHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.IO;
using System.Net;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -13,180 +14,200 @@
using starsky.foundation.storage.Interfaces;
using starsky.foundation.storage.Storage;

namespace starsky.foundation.http.Services
[assembly: InternalsVisibleTo("starskytest")]

namespace starsky.foundation.http.Services;

[Service(typeof(IHttpClientHelper), InjectionLifetime = InjectionLifetime.Singleton)]
public sealed class HttpClientHelper : IHttpClientHelper
{
[Service(typeof(IHttpClientHelper), InjectionLifetime = InjectionLifetime.Singleton)]
public sealed class HttpClientHelper : IHttpClientHelper
/// <summary>
/// These domains are only allowed domains to download from (and https only)
/// </summary>
private readonly List<string> _allowedDomains =
[
"dl.dropboxusercontent.com",
"qdraw.nl", // < used by test and dependencies
"media.qdraw.nl", // < used by demo
"locker.ifttt.com",
"download.geonames.org",
"exiftool.org",
"api.github.com",
"starsky-dependencies.netlify.app"
];

/// <summary>
/// Http Provider
/// </summary>
private readonly IHttpProvider _httpProvider;

private readonly IWebLogger _logger;
private readonly IStorage? _storage;

internal HttpClientHelper(IHttpProvider httpProvider,
IStorage? storage, IWebLogger logger)
{
private readonly IStorage? _storage;

/// <summary>
/// Set Http Provider
/// </summary>
/// <param name="httpProvider">IHttpProvider</param>
/// <param name="serviceScopeFactory">ScopeFactory contains a IStorageSelector</param>
/// <param name="logger">WebLogger</param>
public HttpClientHelper(IHttpProvider httpProvider,
IServiceScopeFactory? serviceScopeFactory, IWebLogger logger)
{
_httpProvider = httpProvider;
_logger = logger;
if ( serviceScopeFactory == null )
{
return;
}
_httpProvider = httpProvider;
_logger = logger;
_storage = storage;
}

using ( var scope = serviceScopeFactory.CreateScope() )
{
// ISelectorStorage is a scoped service
var selectorStorage = scope.ServiceProvider.GetRequiredService<ISelectorStorage>();
_storage = selectorStorage.Get(SelectorStorage.StorageServices.HostFilesystem);
}
/// <summary>
/// Set Http Provider
/// </summary>
/// <param name="httpProvider">IHttpProvider</param>
/// <param name="serviceScopeFactory">ScopeFactory contains a IStorageSelector</param>
/// <param name="logger">WebLogger</param>
public HttpClientHelper(IHttpProvider httpProvider,
IServiceScopeFactory? serviceScopeFactory, IWebLogger logger)
{
_httpProvider = httpProvider;
_logger = logger;
if ( serviceScopeFactory == null )
{
return;
}

/// <summary>
/// Http Provider
/// </summary>
private readonly IHttpProvider _httpProvider;

private readonly IWebLogger _logger;

/// <summary>
/// These domains are only allowed domains to download from (and https only)
/// </summary>
private readonly List<string> _allowedDomains =
[
"dl.dropboxusercontent.com",
"qdraw.nl", // < used by test
"media.qdraw.nl", // < used by demo
"locker.ifttt.com",
"download.geonames.org",
"exiftool.org",
"api.github.com"
];

public async Task<KeyValuePair<bool, string>> ReadString(string sourceHttpUrl)
using ( var scope = serviceScopeFactory.CreateScope() )
{
var sourceUri = new Uri(sourceHttpUrl);
// ISelectorStorage is a scoped service
var selectorStorage = scope.ServiceProvider.GetRequiredService<ISelectorStorage>();
_storage = selectorStorage.Get(SelectorStorage.StorageServices.HostFilesystem);
}
}

_logger.LogInformation("[ReadString] HttpClientHelper > "
+ sourceUri.Host + " ~ " + sourceHttpUrl);
public async Task<KeyValuePair<bool, string>> ReadString(string sourceHttpUrl)
{
var sourceUri = new Uri(sourceHttpUrl);
return await ReadString(sourceUri);
}

// allow whitelist and https only
if ( !_allowedDomains.Contains(sourceUri.Host) || sourceUri.Scheme != "https" )
{
return
public async Task<KeyValuePair<bool, string>> ReadString(Uri sourceHttpUrl)
{
_logger.LogInformation("[ReadString] HttpClientHelper > "
+ sourceHttpUrl);
// allow whitelist and https only
if ( !_allowedDomains.Contains(sourceHttpUrl.Host) || sourceHttpUrl.Scheme != "https" )
{
return
new KeyValuePair<bool, string>(false, string.Empty);
}
}

try
{
using ( HttpResponseMessage response = await _httpProvider.GetAsync(sourceHttpUrl) )
using ( Stream streamToReadFrom = await response.Content.ReadAsStreamAsync() )
{
var reader = new StreamReader(streamToReadFrom, Encoding.UTF8);
var result = await reader.ReadToEndAsync();
return new KeyValuePair<bool, string>(response.StatusCode == HttpStatusCode.OK, result);
}
}
catch ( HttpRequestException exception )
try
{
using ( var response = await _httpProvider.GetAsync(sourceHttpUrl.ToString()) )
using ( var streamToReadFrom = await response.Content.ReadAsStreamAsync() )
{
return new KeyValuePair<bool, string>(false, exception.Message);
var reader = new StreamReader(streamToReadFrom, Encoding.UTF8);
var result = await reader.ReadToEndAsync();
return new KeyValuePair<bool, string>(response.StatusCode == HttpStatusCode.OK,
result);
}
}

public async Task<KeyValuePair<bool, string>> PostString(string sourceHttpUrl,
HttpContent? httpContent, bool verbose = true)
catch ( HttpRequestException exception )
{
var sourceUri = new Uri(sourceHttpUrl);
return new KeyValuePair<bool, string>(false, exception.Message);
}
}

if ( verbose )
{
_logger.LogInformation("[PostString] HttpClientHelper > "
+ sourceUri.Host + " ~ " + sourceHttpUrl);
}
public async Task<KeyValuePair<bool, string>> PostString(string sourceHttpUrl,
HttpContent? httpContent, bool verbose = true)
{
var sourceUri = new Uri(sourceHttpUrl);

// // allow whitelist and https only
if ( !_allowedDomains.Contains(sourceUri.Host) || sourceUri.Scheme != "https" )
{
return
if ( verbose )
{
_logger.LogInformation("[PostString] HttpClientHelper > "
+ sourceUri.Host + " ~ " + sourceHttpUrl);
}

// // allow whitelist and https only
if ( !_allowedDomains.Contains(sourceUri.Host) || sourceUri.Scheme != "https" )
{
return
new KeyValuePair<bool, string>(false, string.Empty);
}
}

try
{
using ( HttpResponseMessage response = await _httpProvider.PostAsync(sourceHttpUrl, httpContent) )
using ( Stream streamToReadFrom = await response.Content.ReadAsStreamAsync() )
{
var reader = new StreamReader(streamToReadFrom, Encoding.UTF8);
var result = await reader.ReadToEndAsync();
return new KeyValuePair<bool, string>(response.StatusCode == HttpStatusCode.OK, result);
}
}
catch ( HttpRequestException exception )
try
{
using ( var response = await _httpProvider.PostAsync(sourceHttpUrl, httpContent) )
using ( var streamToReadFrom = await response.Content.ReadAsStreamAsync() )
{
return new KeyValuePair<bool, string>(false, exception.Message);
var reader = new StreamReader(streamToReadFrom, Encoding.UTF8);
var result = await reader.ReadToEndAsync();
return new KeyValuePair<bool, string>(response.StatusCode == HttpStatusCode.OK,
result);
}
}
catch ( HttpRequestException exception )
{
return new KeyValuePair<bool, string>(false, exception.Message);
}
}

public async Task<bool> Download(string sourceHttpUrl, string fullLocalPath,
int retryAfterInSeconds = 15)
{
var sourceUri = new Uri(sourceHttpUrl);
return await Download(sourceUri, fullLocalPath, retryAfterInSeconds);
}

/// <summary>
/// Downloads the specified source HTTPS URL.
/// </summary>
/// <param name="sourceHttpUrl">The source HTTPS URL.</param>
/// <param name="fullLocalPath">The full local path.</param>
/// <param name="retryAfterInSeconds">Retry after number of seconds</param>
/// <returns></returns>
public async Task<bool> Download(string sourceHttpUrl, string fullLocalPath, int retryAfterInSeconds = 15)
/// <summary>
/// Downloads the specified source HTTPS URL.
/// </summary>
/// <param name="sourceUri">The source HTTPS URL.</param>
/// <param name="fullLocalPath">The full local path.</param>
/// <param name="retryAfterInSeconds">Retry after number of seconds</param>
/// <returns></returns>
public async Task<bool> Download(Uri sourceUri, string fullLocalPath,
int retryAfterInSeconds = 15)
{
if ( _storage == null )
{
if ( _storage == null )
{
throw new EndOfStreamException("is null " + nameof(_storage));
}
throw new EndOfStreamException("is null " + nameof(_storage));
}

Uri sourceUri = new Uri(sourceHttpUrl);
_logger.LogInformation("[Download] HttpClientHelper > "
+ " ~ " + sourceUri);

// allow whitelist and https only
if ( !_allowedDomains.Contains(sourceUri.Host) ||
sourceUri.Scheme != "https" )
{
_logger.LogInformation("[Download] HttpClientHelper > "
+ sourceUri.Host + " ~ " + sourceHttpUrl);
+ "skip: domain not whitelisted " + " ~ " + sourceUri);
return false;
}

// allow whitelist and https only
if ( !_allowedDomains.Contains(sourceUri.Host) ||
sourceUri.Scheme != "https" )
async Task<bool> DownloadAsync()
{
using var response = await _httpProvider.GetAsync(sourceUri.ToString());
await using var streamToReadFrom = await response.Content.ReadAsStreamAsync();
if ( response.StatusCode != HttpStatusCode.OK )
{
_logger.LogInformation("[Download] HttpClientHelper > "
+ "skip: domain not whitelisted " + " ~ " + sourceHttpUrl);
_logger.LogInformation("[Download] HttpClientHelper > " +
response.StatusCode + " ~ " + sourceUri);
return false;
}

async Task<bool> DownloadAsync()
{
using var response = await _httpProvider.GetAsync(sourceHttpUrl);
await using var streamToReadFrom = await response.Content.ReadAsStreamAsync();
if ( response.StatusCode != HttpStatusCode.OK )
{
_logger.LogInformation("[Download] HttpClientHelper > " +
response.StatusCode + " ~ " + sourceHttpUrl);
return false;
}

await _storage!.WriteStreamAsync(streamToReadFrom, fullLocalPath);
return true;
}
await _storage!.WriteStreamAsync(streamToReadFrom, fullLocalPath);
return true;
}

try
{
return await RetryHelper.DoAsync(DownloadAsync,
TimeSpan.FromSeconds(retryAfterInSeconds), 2);
}
catch ( AggregateException exception )
try
{
return await RetryHelper.DoAsync(DownloadAsync,
TimeSpan.FromSeconds(retryAfterInSeconds), 2);
}
catch ( AggregateException exception )
{
foreach ( var innerException in exception.InnerExceptions )
{
foreach ( var innerException in exception.InnerExceptions )
{
_logger.LogError(innerException, $"[Download] InnerException: {exception.Message}");
}
_logger.LogError(exception, $"[Download] Exception: {exception.Message}");
return false;
_logger.LogError(innerException, $"[Download] InnerException: {exception.Message}");
}

_logger.LogError(exception, $"[Download] Exception: {exception.Message}");
return false;
}
}

}
Loading
Loading