Files
VRCX/Dotnet/ImageCache.cs
Natsumi 938fff63d0 Electron support for Linux (#1074)
* init

* SQLite changes

* Move html folder, edit build scripts

* AppApi interface

* Build flags

* AppApi inheritance

* Finishing touches

* Merge upstream changes

* Test CI

* Fix class inits

* Rename AppApi

* Merge upstream changes

* Fix SQLiteLegacy on Linux, Add Linux interop, build tools

* Linux specific localisation strings

* Make it run

* Bring back most of Linux functionality

* Clean up

* Fix TTS voices

* Fix UI var

* Changes

* Electron minimise to tray

* Remove separate toggle for WlxOverlay

* Fixes

* Touchups

* Move csproj

* Window zoom, Desktop Notifications, VR check on Linux

* Fix desktop notifications, VR check spam

* Fix building on Linux

* Clean up

* Fix WebApi headers

* Rewrite VRCX updater

* Clean up

* Linux updater

* Add Linux to build action

* init

* SQLite changes

* Move html folder, edit build scripts

* AppApi interface

* Build flags

* AppApi inheritance

* Finishing touches

* Merge upstream changes

* Test CI

* Fix class inits

* Rename AppApi

* Merge upstream changes

* Fix SQLiteLegacy on Linux, Add Linux interop, build tools

* Linux specific localisation strings

* Make it run

* Bring back most of Linux functionality

* Clean up

* Fix TTS voices

* Changes

* Electron minimise to tray

* Remove separate toggle for WlxOverlay

* Fixes

* Touchups

* Move csproj

* Window zoom, Desktop Notifications, VR check on Linux

* Fix desktop notifications, VR check spam

* Fix building on Linux

* Clean up

* Fix WebApi headers

* Rewrite VRCX updater

* Clean up

* Linux updater

* Add Linux to build action

* Test updater

* Rebase and handle merge conflicts

* Fix Linux updater

* Fix Linux app restart

* Fix friend order

* Handle AppImageInstaller, show an install message on Linux

* Updates to the AppImage installer

* Fix Linux updater, fix set version, check for .NET, copy wine prefix

* Handle random errors

* Rotate tall prints

* try fix Linux restart bug

* Final

---------

Co-authored-by: rs189 <35667100+rs189@users.noreply.github.com>
2025-01-11 13:09:44 +13:00

117 lines
4.0 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
namespace VRCX;
internal static class ImageCache
{
private static readonly string cacheLocation;
private static readonly HttpClient httpClient;
private static readonly List<string> _imageHosts =
[
"api.vrchat.cloud",
"files.vrchat.cloud",
"d348imysud55la.cloudfront.net",
"assets.vrchat.com"
];
static ImageCache()
{
cacheLocation = Path.Combine(Program.AppDataDirectory, "ImageCache");
var httpClientHandler = new HttpClientHandler();
if (WebApi.ProxySet)
httpClientHandler.Proxy = WebApi.Proxy;
httpClient = new HttpClient(httpClientHandler);
httpClient.DefaultRequestHeaders.Add("User-Agent", Program.Version);
}
public static async Task<string> GetImage(string url, string fileId, string version)
{
var directoryLocation = Path.Combine(cacheLocation, fileId);
var fileLocation = Path.Combine(directoryLocation, $"{version}.png");
if (File.Exists(fileLocation))
{
Directory.SetLastWriteTimeUtc(directoryLocation, DateTime.UtcNow);
return fileLocation;
}
if (Directory.Exists(directoryLocation))
Directory.Delete(directoryLocation, true);
Directory.CreateDirectory(directoryLocation);
var uri = new Uri(url);
if (!_imageHosts.Contains(uri.Host))
throw new ArgumentException("Invalid image host", url);
var cookieString = string.Empty;
if (WebApi.Instance != null && WebApi.Instance._cookieContainer != null)
{
CookieCollection cookies = WebApi.Instance._cookieContainer.GetCookies(new Uri("https://api.vrchat.cloud"));
foreach (Cookie cookie in cookies)
cookieString += $"{cookie.Name}={cookie.Value};";
}
var request = new HttpRequestMessage(HttpMethod.Get, url);
if (!string.IsNullOrEmpty(cookieString))
request.Headers.Add("Cookie", cookieString);
using (var response = await httpClient.SendAsync(request))
{
response.EnsureSuccessStatusCode();
await using (var fileStream = new FileStream(fileLocation, FileMode.Create, FileAccess.Write, FileShare.None))
{
await response.Content.CopyToAsync(fileStream);
}
}
var cacheSize = Directory.GetDirectories(cacheLocation).Length;
if (cacheSize > 1100)
CleanImageCache();
return fileLocation;
}
private static void CleanImageCache()
{
var dirInfo = new DirectoryInfo(cacheLocation);
var folders = dirInfo.GetDirectories().OrderByDescending(p => p.LastWriteTime).Skip(1000);
foreach (var folder in folders)
{
folder.Delete(true);
}
}
public static async Task<bool> SaveImageToFile(string url, string path)
{
var uri = new Uri(url);
if (!_imageHosts.Contains(uri.Host))
throw new ArgumentException("Invalid image host", url);
var cookieString = string.Empty;
if (WebApi.Instance != null && WebApi.Instance._cookieContainer != null)
{
var cookies = WebApi.Instance._cookieContainer.GetCookies(new Uri("https://api.vrchat.cloud"));
foreach (Cookie cookie in cookies)
cookieString += $"{cookie.Name}={cookie.Value};";
}
var request = new HttpRequestMessage(HttpMethod.Get, url);
if (!string.IsNullOrEmpty(cookieString))
request.Headers.Add("Cookie", cookieString);
using var response = await httpClient.SendAsync(request);
if (!response.IsSuccessStatusCode)
return false;
await using var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
await response.Content.CopyToAsync(fileStream);
return true;
}
}