Add structured logging and better error handling

This commit is contained in:
SirBlob committed 2026-11-01 13:50:26 -05:00
1 parent db4e3c9611
commit 68c7dd76f2
31 files changed
+640 -109

No files matched your search

+88
View File
@@ -0,0 +1,88 @@
package explain
import (
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"io"
"io/fs"
"net"
"syscall"
"ddc/internal/guard"
)
var keptAsIs = []error{
guard.ErrBlockedAddress,
guard.ErrBlockedPort,
guard.ErrTooManyRedirects,
guard.ErrUnsupportedScheme,
}
func Error(err error) string {
if err == nil {
return ""
}
for _, known := range keptAsIs {
if errors.Is(err, known) {
return capitalize(known.Error())
}
}
if message := networkMessage(err); message != "" {
return message
}
if message := fileSystemMessage(err); message != "" {
return message
}
return capitalize(err.Error())
}
func networkMessage(err error) string {
var dnsError *net.DNSError
var certificateError *tls.CertificateVerificationError
var unknownAuthority x509.UnknownAuthorityError
var hostnameError x509.HostnameError
var timeoutError net.Error
switch {
case errors.As(err, &dnsError):
return fmt.Sprintf("Could not find the server %q. Check the link.", dnsError.Name)
case errors.As(err, &certificateError), errors.As(err, &unknownAuthority), errors.As(err, &hostnameError):
return "The server's security certificate is not valid."
case errors.Is(err, syscall.ECONNREFUSED):
return "The server refused the connection."
case errors.Is(err, syscall.ECONNRESET), errors.Is(err, io.ErrUnexpectedEOF):
return "The server closed the connection before the file was complete. Use Retry to continue."
case errors.Is(err, syscall.ENETUNREACH), errors.Is(err, syscall.EHOSTUNREACH):
return "The server could not be reached from this network."
case errors.As(err, &timeoutError) && timeoutError.Timeout():
return "The server took too long to respond."
default:
return ""
}
}
func fileSystemMessage(err error) string {
switch {
case errors.Is(err, syscall.ENOSPC):
return "The disk is full."
case errors.Is(err, fs.ErrPermission):
return "The server does not have permission to write there. Check the folder owner and permissions."
case errors.Is(err, syscall.EROFS):
return "The destination is on a read-only file system."
default:
return ""
}
}
func capitalize(message string) string {
if message == "" {
return message
}
first := message[0]
if first >= 'a' && first <= 'z' {
return string(first-'a'+'A') + message[1:]
}
return message
}