238 lines
6.2 KiB
C#
238 lines
6.2 KiB
C#
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> downloadProgress;
|
|
|
|
private readonly Progress<string> outputProgress;
|
|
|
|
private CancellationTokenSource cts;
|
|
|
|
private class FailedException(string message) : Exception(message) { }
|
|
|
|
public MainForm()
|
|
{
|
|
InitializeComponent();
|
|
|
|
ytdl = new YoutubeDL();
|
|
downloadProgress = new Progress<DownloadProgress>(CaptureProgress);
|
|
outputProgress = new Progress<string>(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<string> 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<string> 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<string> 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<string> 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<CopyPartyResult>(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();
|
|
}
|
|
}
|