100 lines
3.3 KiB
C#
100 lines
3.3 KiB
C#
using System.Net;
|
|
|
|
namespace dy.net.model.dto
|
|
{
|
|
public enum MediaDownloadFailureKind
|
|
{
|
|
None = 0,
|
|
SourceUnavailable = 1,
|
|
SourceForbidden = 2,
|
|
SourceUnauthorized = 3,
|
|
SourceNotFound = 4,
|
|
SourceRateLimited = 5,
|
|
SourceInvalidContent = 6,
|
|
StorageUnavailable = 7,
|
|
IntegrityCheckFailed = 8,
|
|
Cancelled = 9
|
|
}
|
|
|
|
public sealed class MediaDownloadResult
|
|
{
|
|
public bool Success { get; init; }
|
|
public string ActualSavePath { get; init; }
|
|
public MediaDownloadFailureKind FailureKind { get; init; }
|
|
public int? HttpStatusCode { get; init; }
|
|
public string SourceHost { get; init; }
|
|
public int AttemptedUrlCount { get; init; }
|
|
public DateTime? RetryAfter { get; init; }
|
|
public string Message { get; init; }
|
|
|
|
public void Deconstruct(out bool success, out string actualSavePath)
|
|
{
|
|
success = Success;
|
|
actualSavePath = ActualSavePath;
|
|
}
|
|
|
|
public Exception ToException() => FailureKind switch
|
|
{
|
|
MediaDownloadFailureKind.StorageUnavailable => new MediaStorageException(Message ?? "媒体存储写入失败。"),
|
|
MediaDownloadFailureKind.IntegrityCheckFailed => new MediaIntegrityException(Message ?? "媒体完整性校验失败。"),
|
|
MediaDownloadFailureKind.Cancelled => new OperationCanceledException(Message ?? "媒体下载已取消。"),
|
|
_ => new MediaSourceException(FailureKind, Message ?? "媒体来源不可用。", HttpStatusCode, SourceHost, RetryAfter)
|
|
};
|
|
|
|
public static MediaDownloadResult Succeeded(string path, string host, int attempted) => new()
|
|
{
|
|
Success = true,
|
|
ActualSavePath = path,
|
|
SourceHost = host,
|
|
AttemptedUrlCount = attempted
|
|
};
|
|
}
|
|
|
|
public sealed class MediaSourceException : Exception
|
|
{
|
|
public MediaSourceException(
|
|
MediaDownloadFailureKind kind,
|
|
string message,
|
|
int? statusCode = null,
|
|
string sourceHost = null,
|
|
DateTime? retryAfter = null,
|
|
Exception innerException = null) : base(message, innerException)
|
|
{
|
|
FailureKind = kind;
|
|
StatusCode = statusCode;
|
|
SourceHost = sourceHost;
|
|
RetryAfter = retryAfter;
|
|
}
|
|
|
|
public MediaDownloadFailureKind FailureKind { get; }
|
|
public int? StatusCode { get; }
|
|
public string SourceHost { get; }
|
|
public DateTime? RetryAfter { get; }
|
|
}
|
|
|
|
public sealed class MediaStorageException : IOException
|
|
{
|
|
public MediaStorageException(string message, Exception innerException = null) : base(message, innerException) { }
|
|
}
|
|
|
|
public sealed class MediaIntegrityException : IOException
|
|
{
|
|
public MediaIntegrityException(string message, Exception innerException = null) : base(message, innerException) { }
|
|
}
|
|
|
|
public enum SourceFailureDisposition
|
|
{
|
|
Continue = 0,
|
|
WaitForSource = 1,
|
|
RequiresAuthorization = 2
|
|
}
|
|
|
|
public sealed class SourceAccessDecision
|
|
{
|
|
public bool Allowed { get; init; }
|
|
public bool IsProbe { get; init; }
|
|
public string Message { get; init; }
|
|
public DateTime? RetryAt { get; init; }
|
|
}
|
|
}
|