This commit is contained in:
2024-11-18 16:28:45 +02:00
parent f0452ff9f7
commit 825c7e3391
34 changed files with 624 additions and 426 deletions

View File

@@ -1,32 +1,13 @@
package gemini
import (
"errors"
"fmt"
"gemini-grc/logging"
"net/url"
"regexp"
"strconv"
)
func checkGeminiStatusCode(code int) error {
switch {
case code == 20:
return nil
case code >= 10 && code < 20:
return fmt.Errorf("gemini response %d needs data input", code)
case code >= 30 && code < 40:
return fmt.Errorf("gemini response %d redirect", code)
case code >= 40 && code < 50:
return fmt.Errorf("gemini response %d server error", code)
case code >= 50 && code < 60:
return fmt.Errorf("gemini response %d server permanent error", code)
case code >= 60 && code < 70:
return fmt.Errorf("gemini response %d certificate error", code)
default:
return fmt.Errorf("unexpected/unhandled Gemini response %d", code)
}
}
"gemini-grc/logging"
)
func ProcessGemini(snapshot *Snapshot) *Snapshot {
// Grab link lines
@@ -40,7 +21,7 @@ func ProcessGemini(snapshot *Snapshot) *Snapshot {
logging.LogDebug("Cannot normalize URL in line '%s': %v", line, err)
continue
}
geminiUrl, err := ParseUrl(normalizedLink, descr)
geminiUrl, err := ParseURL(normalizedLink, descr)
if err != nil {
logging.LogDebug("Cannot parse URL in link '%s': %v", line, err)
continue
@@ -54,25 +35,6 @@ func ProcessGemini(snapshot *Snapshot) *Snapshot {
return snapshot
}
func ParseUrl(input string, descr string) (*GeminiUrl, error) {
u, err := url.Parse(input)
if err != nil {
return nil, fmt.Errorf("error parsing URL %s: %w", input, err)
}
protocol := u.Scheme
hostname := u.Hostname()
strPort := u.Port()
path := u.Path
if strPort == "" {
strPort = "1965"
}
port, err := strconv.Atoi(strPort)
if err != nil {
return nil, fmt.Errorf("error parsing URL %s: %w", input, err)
}
return &GeminiUrl{Protocol: protocol, Hostname: hostname, Port: port, Path: path, Descr: descr, Full: u.String()}, nil
}
// ExtractLinkLines takes a Gemtext document as a string and returns all lines that are link lines
func ExtractLinkLines(gemtext string) []string {
// Define the regular expression pattern to match link lines
@@ -87,11 +49,11 @@ func ExtractLinkLines(gemtext string) []string {
// NormalizeLink takes a single link line and the current URL,
// return the URL converted to an absolute URL
// and its description.
func NormalizeLink(linkLine string, currentURL string) (link string, descr string, err error) {
func NormalizeLink(linkLine string, currentURL string) (string, string, error) {
// Parse the current URL
baseURL, err := url.Parse(currentURL)
if err != nil {
return "", "", fmt.Errorf("invalid current URL: %v", err)
return "", "", fmt.Errorf("%w: %w", ErrURLParse, err)
}
// Regular expression to extract the URL part from a link line
@@ -101,13 +63,13 @@ func NormalizeLink(linkLine string, currentURL string) (link string, descr strin
matches := re.FindStringSubmatch(linkLine)
if len(matches) == 0 {
// If the line doesn't match the expected format, return it unchanged
return "", "", fmt.Errorf("not a link line: %v", linkLine)
return "", "", fmt.Errorf("%w for link line %s", ErrGeminiLinkLineParse, linkLine)
}
originalURLStr := matches[1]
_, err = url.QueryUnescape(originalURLStr)
if err != nil {
return "", "", fmt.Errorf("error decoding URL: %w", err)
return "", "", fmt.Errorf("%w: %w", ErrURLDecode, err)
}
restOfLine := ""
@@ -119,7 +81,7 @@ func NormalizeLink(linkLine string, currentURL string) (link string, descr strin
parsedURL, err := url.Parse(originalURLStr)
if err != nil {
// If URL parsing fails, return an error
return "", "", fmt.Errorf("invalid URL '%s': %v", originalURLStr, err)
return "", "", fmt.Errorf("%w: %w", ErrURLParse, err)
}
// Resolve relative URLs against the base URL
@@ -151,13 +113,13 @@ func ParseFirstTwoDigits(input string) (int, error) {
// Find the first match in the string
matches := re.FindStringSubmatch(input)
if len(matches) == 0 {
return 0, errors.New("no digits found at the beginning of the string")
return 0, fmt.Errorf("%w", ErrGeminiResponseHeader)
}
// Parse the captured match as an integer
snapshot, err := strconv.Atoi(matches[1])
if err != nil {
return 0, fmt.Errorf("failed to convert matched digits to int: %v", err)
return 0, fmt.Errorf("%w: %w", ErrTextParse, err)
}
return snapshot, nil