public void BuildRequestMessage_WithNullArguments_ThrowsArgumentNullException(string url, Stream file, FileType fileType, ConversionTarget conversionTarget, JObject config) { var requestBuilder = new DocumentConversionRequestBuilder(); var exception = Record.Exception(() => requestBuilder.BuildRequestMessage(url, file, fileType, conversionTarget, config)); Assert.NotNull(exception); Assert.IsType<ArgumentNullException>(exception); }
protected void SetConversionTargetAndNavigate(ConversionTarget conversionTarget) { switch (conversionTarget) { case ConversionTarget.SOLIDITY: ConverterService.ConversionStrategy = new SolidityConversionStrategy(); break; case ConversionTarget.PLUTUS: ConverterService.ConversionStrategy = new PlutusConversionStrategy(); break; } NavigationManager.NavigateTo("generated"); }
/// <summary> /// Builds a HttpRequestMessage based on the options provided. /// </summary> /// <param name="url"></param> /// <param name="file"></param> /// <param name="fileType"></param> /// <param name="config"></param> /// <param name="conversionTarget"></param> /// <exception cref="ArgumentNullException"></exception> /// <returns></returns> internal HttpRequestMessage BuildRequestMessage(string url, Stream file, FileType fileType, ConversionTarget conversionTarget, JObject config = null) { if (string.IsNullOrWhiteSpace(url)) throw new ArgumentNullException(nameof(url)); if (file == null) throw new ArgumentNullException(nameof(file)); if (config == null) config = new JObject(); //Attach the conversion target to the config var jsonSerializer = new JsonSerializer(); var stringEnumConverter = new StringEnumConverter(); jsonSerializer.Converters.Add(stringEnumConverter); config["conversion_target"] = JToken.FromObject(conversionTarget, jsonSerializer); //Serialize the fileType and config to a string var serializedFileType = JsonConvert.SerializeObject(fileType, Formatting.None, stringEnumConverter).Replace("\"", ""); var serializedConfig = config.ToString(Formatting.None, stringEnumConverter); var streamContent = new StreamContent(file); streamContent.Headers.ContentType = MediaTypeHeaderValue.Parse(serializedFileType); // ReSharper disable once ExceptionNotDocumented var content = new MultipartFormDataContent($"{DateTime.UtcNow.Ticks}") { {new StringContent(serializedConfig), "config"}, {streamContent, nameof(file)} }; var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, url) { Content = content }; return httpRequestMessage; }
public static ConversionResult ConvertORF( string filePath, ConversionTarget conversion) { try { using (var mmf = MemoryMappedFile.CreateFromFile( filePath, System.IO.FileMode.Open)) { using (var mvs = mmf.CreateViewStream(0L, 0L, MemoryMappedFileAccess.ReadWrite)) { int[] foundCategory = new int[2] { -1, -1 }; int[] matched = new int[kNumTags]; // Read stream one byte at a time; memory-mapped so should be fast. for (int i; (i = mvs.ReadByte()) >= 0;) { byte b = (byte)i; // Search for all tags in the stream for (int t = 0; t < kNumTags; t++) { // If not already found, try to match next byte in t'th tag. if (matched[t] >= 0) { if (kTags[t].bytes[matched[t]] == b) { // Check if all bytes in the tag have been matched. if (++matched[t] == kTags[t].length) { int category = t & 1; if (foundCategory[category] >= 0) { // If we already have a tag for this category, // something strange is going on. Bail. return(ConversionResult.FileStructureError); } // Record the position of the found tag. foundCategory[category] = (int)mvs.Position - kTags[t].length; // Mark this tag as found. matched[t] = -1; // if (foundCategory[0] >= 0 && foundCategory[1] >= 0) { int mfgIndex = 2 * (int)conversion + kManufacturer; int cameraIndex = 2 * (int)conversion + kCameraModel; // Write manufacturer tag. mvs.Position = foundCategory[0]; mvs.Write(kTags[mfgIndex].bytes, 0, kTags[mfgIndex].length); // Write camera tag. mvs.Position = foundCategory[1]; mvs.Write(kTags[cameraIndex].bytes, 0, kTags[cameraIndex].length); // Success! return(ConversionResult.Success); } } } else if (matched[t] != 0) { matched[t] = (kTags[t].bytes[0] == b) ? 1 : 0; } } } } } } return(ConversionResult.TagsNotFound); } catch { return(ConversionResult.CaughtException); } }
public async Task WriteMetadata(VideoInfo videoInfo, MetaDataInfo info, ConversionTarget target) { string filePath = PathHelper.GenerateFilePath(videoInfo.FileName); if (!File.Exists(filePath)) { return; // just no-op } var tFile = TagLib.File.Create(filePath); tFile.Tag.Title = string.IsNullOrWhiteSpace(info?.Title) ? (videoInfo.VideoTitle ?? PathHelper.GetFilenameWithoutExtension(videoInfo.FileName)) : info.Title; if (target == ConversionTarget.Mp3 && !string.IsNullOrWhiteSpace(info?.Artists)) { tFile.Tag.Performers = new string[] { info.Artists }; } // Check if we even have to fetch and download album art :) if (tFile.Tag.Pictures?.Length > 0) { // Only fetch and set thumbnail once :) tFile.Save(); return; } // Fetch Youtube thumbnail var ytId = PathHelper.GetFilenameWithoutExtension(videoInfo.FileName); string imageName = $"{ytId}.jpg"; string imagePath = Path.Combine(PathHelper.OutputPath, imageName); try { await _httpService.DownloadAndSaveFile(new Uri($"https://i.ytimg.com/vi/{ytId}/maxresdefault.jpg"), imagePath); } catch (Exception) { // If we fail to download the image just return without it it's fine... tFile.Save(); return; } // Add image as album cover :) var imageBytes = File.ReadAllBytes(imagePath); TagLib.Id3v2.AttachedPictureFrame cover = new AttachedPictureFrame() { Type = TagLib.PictureType.FrontCover, Description = "Cover", MimeType = System.Net.Mime.MediaTypeNames.Image.Jpeg, Data = imageBytes, TextEncoding = TagLib.StringType.UTF16 }; tFile.Tag.Pictures = new IPicture[] { cover }; tFile.Save(); // Remove file if it exists. if (File.Exists(imagePath)) { File.Delete(imagePath); } }
public static string GenerateExtensionOnFilename(string filename, ConversionTarget target, uint?quality = null) => target switch {
public async Task BuildRequestMessage_Equal(int fileLength, FileType fileType, ConversionTarget conversionTarget, string mockConfig, string expectedConfig, string expectedMediaType) { dynamic config = null; if (!string.IsNullOrWhiteSpace(mockConfig)) config = JObject.Parse(mockConfig); var requestBuilder = new DocumentConversionRequestBuilder(); using (var ms = new MemoryStream(new byte[fileLength])) { var request = requestBuilder.BuildRequestMessage(ServiceUrl, ms, fileType, conversionTarget, config); Assert.NotNull(request); Assert.Equal(ServiceUrl, request.RequestUri.ToString()); Assert.Equal(HttpMethod.Post, request.Method); var content = (MultipartFormDataContent) request.Content; var fileContent = (StreamContent) content.FirstOrDefault(x => x.Headers.ContentDisposition.Name == "file"); var configContent = (StringContent) content.FirstOrDefault(x => x.Headers.ContentDisposition.Name == "config"); Assert.NotNull(fileContent); Assert.NotNull(configContent); var file = await fileContent.ReadAsByteArrayAsync().ConfigureAwait(false); Assert.Equal(ms.Length, file.Length); Assert.Equal(expectedConfig, await configContent.ReadAsStringAsync().ConfigureAwait(false)); Assert.Equal(expectedMediaType, fileContent.Headers.ContentType.MediaType); } }
/// <summary> /// Tries to download and convert video and return Filename with extension /// </summary> public async Task <Result <VideoInfo, Error> > TryDownload(string url, ConversionTarget target, uint?quality = null) { await Task.Yield(); // Force a new thread. if (target == ConversionTarget.Mp4 && !quality.HasValue) { return(new Result <VideoInfo, Error>(new Error("Quality cannot be null if conversion target is mp4!"))); } url = CleanYtLink(url); var ytId = GetYoutubeId(url); if (!ytId) { return(new Result <VideoInfo, Error>(new Error("Not a valid YT link"))); } string fileName = PathHelper.GenerateExtensionOnFilename(~ytId, target, quality); // Check Cache first if (_cacheService.TryGetFile(fileName, out var cachedVideoInfo)) { return(new Result <VideoInfo, Error>(cachedVideoInfo)); } var jsonCheck = YtJsonDownload(url); using var ytJsonProc = Process.Start(jsonCheck); if (ytJsonProc == null) { return(new Result <VideoInfo, Error>(new Error("Failed to fetch video JSON info"))); } string output = await ytJsonProc.StandardOutput.ReadToEndAsync(); ytJsonProc.WaitForExit(); if (ytJsonProc.ExitCode != 0) { return(new Result <VideoInfo, Error>(new Error("Failed to fetch video JSON info"))); } IDictionary <string, JToken> jsonDict = JObject.Parse(output); if (jsonDict.ContainsKey("is_live") && !string.IsNullOrWhiteSpace(jsonDict["is_live"].Value <string>())) { return(new Result <VideoInfo, Error>(new Error("Livestreams are not allowed"))); } var ytdlInfo = YtDl(url, ~ytId, target, quality ?? 720); using var ytDlProc = Process.Start(ytdlInfo); if (ytDlProc == null) { return(new Result <VideoInfo, Error>(new Error("Failed to download video"))); } ytDlProc.WaitForExit(); string filePath = PathHelper.GenerateFilePath(fileName); if (!File.Exists(filePath)) { _cacheService.CleanupFilesNotInCache(); return(new Result <VideoInfo, Error>(new Error("Failed to download video"))); } string videoTitle = jsonDict["title"].Value <string>(); var videoInfo = new VideoInfo() { VideoTitle = videoTitle, FileName = fileName }; // Add to cache service _cacheService.TryAddFile(fileName, videoInfo); return(videoInfo); }
/// <summary> /// Tries to download and convert video and return Filename with extension /// </summary> public async Task <Result <VideoInfo, Error> > TryDownloadAsync(string url, ConversionTarget target, uint?quality = null) => await Task.Run(async() => await this.TryDownload(url, target, quality));
private string GenerateArgumentList(string url, string name, ConversionTarget target, uint res = 720) => target switch {
private ProcessStartInfo YtDl(string url, string name, ConversionTarget target, uint quality) => new ProcessStartInfo() { FileName = _config.YtDlPath, Arguments = GenerateArgumentList(url, name, target, quality) };