diff --git a/app_llm.go b/app_llm.go index 98bd5d93..422526ad 100644 --- a/app_llm.go +++ b/app_llm.go @@ -373,7 +373,22 @@ func (app *App) getSuggestedCreatedDate(ctx context.Context, content string, log result := stripReasoning(completion.Choices[0].Content) return strings.TrimSpace(strings.Trim(result, "\"")), nil } +var xmlAttrEscaper = strings.NewReplacer( + "&", "&", + `"`, """, + "'", "'", + "<", "<", + ">", ">", +) + +var xmlTextEscaper = strings.NewReplacer( + "&", "&", + "<", "<", + ">", ">", +) +func escapeXMLAttr(s string) string { return xmlAttrEscaper.Replace(s) } +func escapeXMLText(s string) string { return xmlTextEscaper.Replace(s) } // getSuggestedCustomFields generates suggested custom fields for a document using the LLM func (app *App) getSuggestedCustomFields(ctx context.Context, doc Document, selectedFieldIDs []int, logger *logrus.Entry) ([]CustomFieldSuggestion, error) { // Fetch all available custom fields @@ -401,7 +416,15 @@ func (app *App) getSuggestedCustomFields(ctx context.Context, doc Document, sele var xmlBuilder strings.Builder xmlBuilder.WriteString("\n") for _, field := range selectedCustomFields { - xmlBuilder.WriteString(fmt.Sprintf(" \n", field.Name, field.DataType)) + if field.DataType == "select" && field.ExtraData != nil && len(field.ExtraData.SelectOptions) > 0 { + xmlBuilder.WriteString(fmt.Sprintf(" \n", escapeXMLAttr(field.Name), escapeXMLAttr(field.DataType))) + for _, opt := range field.ExtraData.SelectOptions { + xmlBuilder.WriteString(fmt.Sprintf(" \n", escapeXMLAttr(opt.ID), escapeXMLText(opt.Label))) + } + xmlBuilder.WriteString(" \n") + } else { + xmlBuilder.WriteString(fmt.Sprintf(" \n", escapeXMLAttr(field.Name), escapeXMLAttr(field.DataType))) + } } xmlBuilder.WriteString("") customFieldsXML := xmlBuilder.String() diff --git a/paperless.go b/paperless.go index 170658db..e4d716ee 100644 --- a/paperless.go +++ b/paperless.go @@ -39,10 +39,20 @@ type PaperlessClient struct { } // CustomField represents a custom field from the Paperless-ngx API +type SelectOption struct { + ID string `json:"id"` + Label string `json:"label"` +} + +type CustomFieldExtraData struct { + SelectOptions []SelectOption `json:"select_options"` +} + type CustomField struct { - ID int `json:"id"` - Name string `json:"name"` - DataType string `json:"data_type"` + ID int `json:"id"` + Name string `json:"name"` + DataType string `json:"data_type"` + ExtraData *CustomFieldExtraData `json:"extra_data"` } // DocumentType represents a document type from the Paperless-ngx API