221 lines
No EOL
8 KiB
C#
221 lines
No EOL
8 KiB
C#
using SixLabors.ImageSharp;
|
|
using SixLabors.ImageSharp.Processing;
|
|
using System.Diagnostics.Metrics;
|
|
|
|
namespace wp2ghost
|
|
{
|
|
// =============================================================================
|
|
// ImageManager — Bilder herunterladen, cachen, lokal verwalten
|
|
// =============================================================================
|
|
static class ImageManager
|
|
{
|
|
private static readonly HttpClient httpClient = new();
|
|
private static Dictionary<string, (string RelativePath, string LocalPath)> Cache = new();
|
|
private static List<(string RelativePath, string LocalPath)> FilesToZip = new();
|
|
private static string LocalImageDir = "";
|
|
private static string CachePath = "";
|
|
|
|
|
|
public static IReadOnlyList<(string RelativePath, string LocalPath)> CachedFiles => FilesToZip;
|
|
public static bool TryGetRelativePath(string url, out string relativePath)
|
|
{
|
|
if (Cache.TryGetValue(url, out var cached))
|
|
{
|
|
relativePath = cached.RelativePath;
|
|
return true;
|
|
}
|
|
relativePath = "";
|
|
return false;
|
|
}
|
|
|
|
public static void Init(string baseDir)
|
|
{
|
|
LocalImageDir = Path.Combine(baseDir, "images");
|
|
CachePath = Path.Combine(baseDir, "imagecache.txt");
|
|
|
|
if (!Directory.Exists(LocalImageDir))
|
|
Directory.CreateDirectory(LocalImageDir);
|
|
|
|
LoadCache();
|
|
}
|
|
|
|
public static string ImageContainerPath => LocalImageDir;
|
|
|
|
public static void SaveCache()
|
|
{
|
|
var lines = new List<string>();
|
|
foreach (var kvp in Cache)
|
|
lines.Add($"{kvp.Key}|{kvp.Value.RelativePath}|{kvp.Value.LocalPath}");
|
|
File.WriteAllLines(CachePath, lines);
|
|
}
|
|
|
|
public static void ClearAll()
|
|
{
|
|
if (Directory.Exists(LocalImageDir))
|
|
{
|
|
Directory.Delete(LocalImageDir, true);
|
|
Directory.CreateDirectory(LocalImageDir);
|
|
}
|
|
Cache.Clear();
|
|
FilesToZip.Clear();
|
|
SaveCache();
|
|
Console.WriteLine("Bilder wurden lokal gelöscht.");
|
|
}
|
|
|
|
public static void ShowInfo()
|
|
{
|
|
if (Cache.Count > 0)
|
|
{
|
|
Console.WriteLine("\nLokal gespeicherte Bilder:");
|
|
foreach (var kvp in Cache.Take(20))
|
|
Console.WriteLine($" {kvp.Key} -> images/{kvp.Value.RelativePath}");
|
|
if (Cache.Count > 20)
|
|
Console.WriteLine($" ... und {Cache.Count - 20} weitere");
|
|
}
|
|
}
|
|
|
|
public static bool IsMainImage(string url)
|
|
{
|
|
if (string.IsNullOrEmpty(url)) return false;
|
|
try
|
|
{
|
|
var uri = new Uri(url);
|
|
string fileName = Path.GetFileName(uri.LocalPath);
|
|
// WordPress-Sizes: -300x200, -scaled, -1024x768 etc.
|
|
if (System.Text.RegularExpressions.Regex.IsMatch(fileName, @"-\d+x\d+(?=\.\w+$)"))
|
|
return false;
|
|
if (fileName.Contains("-scaled"))
|
|
return false;
|
|
return true;
|
|
}
|
|
catch { return false; }
|
|
}
|
|
|
|
public static async Task<(string RelativePath, string LocalPath)?> DownloadAsync(string imageUrl, DateTime? postDate)
|
|
{
|
|
if (string.IsNullOrEmpty(imageUrl) || !Uri.IsWellFormedUriString(imageUrl, UriKind.Absolute))
|
|
return null;
|
|
|
|
if (Cache.TryGetValue(imageUrl, out var cachedFile))
|
|
{
|
|
if (File.Exists(cachedFile.LocalPath))
|
|
return cachedFile;
|
|
Cache.Remove(imageUrl);
|
|
}
|
|
|
|
try
|
|
{
|
|
string fileName = Path.GetFileName(new Uri(imageUrl).AbsolutePath);
|
|
string urlHash = GetHashCode(imageUrl);
|
|
var datePrefix = DateTime.Now;
|
|
string datePath = $"{datePrefix:yyyy}/{datePrefix:MM}";
|
|
var localPath = Path.Combine(LocalImageDir, datePath);
|
|
if (!string.IsNullOrEmpty(localPath) && !Directory.Exists(localPath))
|
|
Directory.CreateDirectory(localPath);
|
|
|
|
var counter = 1 + new DirectoryInfo(localPath).GetFiles().Length;
|
|
var pDate = postDate ?? DateTime.Now;
|
|
string uniqueFileName = $"{pDate:yyyymmdd}_{counter}{Path.GetExtension(fileName)}";
|
|
string relativePath = $"{datePath}/{uniqueFileName}";
|
|
string fallBackPath = $"{datePath}/{uniqueFileName}";
|
|
localPath = Path.Combine(LocalImageDir, relativePath);
|
|
fallBackPath = Path.Combine(LocalImageDir, fallBackPath);
|
|
|
|
|
|
|
|
|
|
if (File.Exists(fallBackPath))
|
|
{
|
|
File.Move(fallBackPath, localPath);
|
|
Console.WriteLine($" [Bild] Bereits vorhanden: {relativePath}");
|
|
}
|
|
else if (!File.Exists(localPath))
|
|
{
|
|
byte[] imageBytes = await httpClient.GetByteArrayAsync(imageUrl);
|
|
await File.WriteAllBytesAsync(localPath, imageBytes);
|
|
Console.WriteLine($" [Bild] Heruntergeladen: {relativePath}");
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($" [Bild] Bereits vorhanden: {relativePath}");
|
|
}
|
|
|
|
ResizeImage(localPath);
|
|
|
|
var fileResult = (relativePath, localPath);
|
|
Cache[imageUrl] = fileResult;
|
|
FilesToZip.Add(fileResult);
|
|
return fileResult;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($" [Bild-Fehler] Konnte {imageUrl} nicht laden: {ex.Message}");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static void ResizeImage(string localPath)
|
|
{
|
|
const int maxSize = 1024;
|
|
try
|
|
{
|
|
using var image = Image.Load(localPath);
|
|
int width = image.Width;
|
|
int height = image.Height;
|
|
|
|
int longEdge = Math.Max(width, height);
|
|
if (longEdge <= maxSize) return;
|
|
|
|
int newWidth, newHeight;
|
|
if (width >= height)
|
|
{
|
|
newWidth = maxSize;
|
|
newHeight = (int)Math.Round(height * ((double)maxSize / width));
|
|
}
|
|
else
|
|
{
|
|
newHeight = maxSize;
|
|
newWidth = (int)Math.Round(width * ((double)maxSize / height));
|
|
}
|
|
|
|
image.Mutate(x => x.Resize(newWidth, newHeight));
|
|
image.Save(localPath);
|
|
Console.WriteLine($" [Bild] Angepasst: {width}x{height} → {newWidth}x{newHeight}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($" [Bild-Warnung] Resize fehlgeschlagen für {Path.GetFileName(localPath)}: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private static string GetHashCode(string input)
|
|
{
|
|
unchecked
|
|
{
|
|
int hash = 17;
|
|
foreach (char c in input)
|
|
hash = hash * 23 + c;
|
|
return hash.ToString("x8");
|
|
}
|
|
}
|
|
|
|
private static void LoadCache()
|
|
{
|
|
if (!File.Exists(CachePath)) return;
|
|
try
|
|
{
|
|
var lines = File.ReadAllLines(CachePath);
|
|
foreach (var line in lines)
|
|
{
|
|
var parts = line.Split('|');
|
|
if (parts.Length == 3)
|
|
Cache[parts[0]] = (parts[1], parts[2]);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Fehler beim Laden des Bild-Caches: {ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
} |