using Microsoft.Extensions.Logging; using Microsoft.VisualBasic.ApplicationServices; using Newtonsoft.Json; using System.Media; using System.Security.Policy; using System.Text.Json.Serialization; using System.Threading.Tasks; using System.Windows.Forms; using System.Xml; using YoutubeDLSharp; namespace Marro.VRChatYouTubeWorkaround; public partial class MainForm : Form { private readonly YoutubeDL ytdl; private readonly Progress downloadProgress; private readonly Progress outputProgress; private CancellationTokenSource cts; private class FailedException(string message) : Exception(message) { } public MainForm() { InitializeComponent(); ytdl = new YoutubeDL(); downloadProgress = new Progress(CaptureProgress); outputProgress = new Progress(WriteLog); prgProgress.Maximum = 100; } private void btnGo_Click(object sender, EventArgs e) { ClearLog(); ResetProgress(); var url = txtInputUrl.Text.Trim(); if (string.IsNullOrEmpty(url)) { WriteStatus("Enter a url!"); return; } cts = new CancellationTokenSource(); var cancellationToken = cts.Token; var task = Task.Run(() => ProcessVideo(url, cancellationToken)); task.ContinueWith(ProcessVideoShowResult); grpInputUrl.Enabled = false; btnCancel.Enabled = true; } private async Task ProcessVideo(string sourceUrl, CancellationToken cancellationToken) { string filePath = ""; try { filePath = await DownloadVideoToFile(sourceUrl, cancellationToken); cancellationToken.ThrowIfCancellationRequested(); WriteStatus("Uploading video..."); var url = await UploadFile(filePath, cancellationToken); return url; } finally { File.Delete(filePath); } } private void ProcessVideoShowResult(Task task) { if (InvokeRequired) { Invoke(() => ProcessVideoShowResult(task)); return; } grpInputUrl.Enabled = true; btnCancel.Enabled = false; if (cts.IsCancellationRequested || task.IsCanceled) { WriteStatus("Cancelled."); ResetProgress(); return; } if (task.IsFaulted) { WriteLog($"{task.Exception.InnerException}"); WriteStatus("Failed."); ResetProgress(); return; } var url = task.Result; txtResultUrl.Text = url; WriteLog($"Final URL: {url}"); WriteStatus("Finished."); Clipboard.SetText(url); Chime(); } private async Task DownloadVideoToFile(string url, CancellationToken cancellationToken) { WriteStatus("Downloading required files..."); await Utils.DownloadBinaries(); WriteStatus("Downloading video..."); var res = await ytdl.RunVideoDownload(url, format: "mp4", progress: downloadProgress, output: outputProgress, ct: cancellationToken); if (!res.Success) { throw new FailedException("Failed to download video!"); } return res.Data; } private static async Task UploadFile(string filePath, CancellationToken cancellationToken) { var url = new Uri("https://media.komawo.gay/"); url = new Uri(url, $"{Path.GetFileName(filePath)}?j"); using var client = new HttpClient(); using var fileStream = File.OpenRead(filePath); using var content = new StreamContent(fileStream); content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("video/mp4"); content.Headers.Add("pw", "Luminance7-Trapper0-Choice6-Brunette9-Abacus7"); content.Headers.Add("want", "url"); content.Headers.Add("ck", "no"); content.Headers.Add("replace", "1"); var response = await client.PutAsync(url, content, cancellationToken); cancellationToken.ThrowIfCancellationRequested(); response.EnsureSuccessStatusCode(); var responseJson = await response.Content.ReadAsStringAsync(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); var responseObject = JsonConvert.DeserializeObject(responseJson); return responseObject?.FileUrl ?? throw new FailedException("Failed to get url for uploaded video!"); } private class CopyPartyResult { [JsonProperty("filesz")] public int? FileSZ { get; set; } [JsonProperty("fileurl")] public string? FileUrl { get; set; } } private void WriteLog(string message) { if (InvokeRequired) { Invoke(() => WriteLog(message)); return; } txtLog.AppendText($"{message}{Environment.NewLine}"); } private void WriteStatus(string message) { if (InvokeRequired) { Invoke(() => WriteStatus(message)); return; } lblStatus.Text = message; } private void ClearLog() { txtLog.Clear(); } private void Chime() { SoundPlayer simpleSound = new SoundPlayer(@"C:\Windows\Media\Windows Background.wav"); try { simpleSound.Play(); } catch { // Playing sound is not critical } } private void CaptureProgress(DownloadProgress progress) { var newValue = (int)(progress.Progress * 100); var step = newValue - prgProgress.Value; if (step <= 0) { return; } prgProgress.Step = step; prgProgress.PerformStep(); } private void ResetProgress() { prgProgress.Value = 0; } private void btnCopy_Click(object sender, EventArgs e) { Clipboard.SetText(txtResultUrl.Text); } private void btnPasteAndGo_Click(object sender, EventArgs e) { txtInputUrl.Text = Clipboard.GetText(); btnGo.PerformClick(); } private void btnCancel_Click(object sender, EventArgs e) { cts?.Cancel(); } }