go-guess/backend/internal/service/cv.go
2026-09-19 20:31:14 +02:00

78 lines
1.7 KiB
Go

package service
import (
"archive/zip"
"bytes"
"encoding/xml"
"fmt"
"io"
"path/filepath"
"strings"
"github.com/ledongthuc/pdf"
)
func extractCVText(filename string, content []byte) (text string, err error) {
if len(content) == 0 {
return "", nil
}
switch strings.ToLower(filepath.Ext(filename)) {
case ".pdf":
defer func() {
if recovered := recover(); recovered != nil {
text = ""
err = fmt.Errorf("unreadable PDF")
}
}()
reader, err := pdf.NewReader(bytes.NewReader(content), int64(len(content)))
if err != nil {
return "", fmt.Errorf("read PDF: %w", err)
}
plainText, err := reader.GetPlainText()
if err != nil {
return "", fmt.Errorf("extract PDF text: %w", err)
}
value, err := io.ReadAll(plainText)
if err != nil {
return "", fmt.Errorf("read PDF text: %w", err)
}
return string(value), nil
case ".docx":
return extractDOCX(content)
default:
return string(content), nil
}
}
func extractDOCX(content []byte) (string, error) {
archive, err := zip.NewReader(bytes.NewReader(content), int64(len(content)))
if err != nil {
return "", fmt.Errorf("open DOCX: %w", err)
}
for _, file := range archive.File {
if file.Name != "word/document.xml" {
continue
}
stream, err := file.Open()
if err != nil {
return "", fmt.Errorf("open DOCX document: %w", err)
}
defer stream.Close()
decoder := xml.NewDecoder(stream)
var text strings.Builder
for {
token, err := decoder.Token()
if err == io.EOF {
return text.String(), nil
}
if err != nil {
return "", fmt.Errorf("parse DOCX document: %w", err)
}
if chars, ok := token.(xml.CharData); ok {
text.Write(chars)
text.WriteByte(' ')
}
}
}
return "", fmt.Errorf("DOCX document body is missing")
}