1
0
Fork 0
mirror of https://github.com/miniflux/v2.git synced 2025-08-16 18:01:37 +00:00
miniflux-v2/internal/reader/opml/serializer.go
jvoisin 93fc206f42 refactor(opml): reduce indirections
Don't use a slice of pointers to opml items, when we can simply use a slice of
items instead. This should reduce the amount of memory allocations and the
number of indirections the GC has to process, speedup up the import process.

Note that this doesn't introduce any additional copies, as the only time a
slice of subscription is created, the items are created and inserted inline.
2025-08-12 19:47:47 -07:00

73 lines
2 KiB
Go

// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package opml // import "miniflux.app/v2/internal/reader/opml"
import (
"bufio"
"bytes"
"encoding/xml"
"log/slog"
"sort"
"time"
)
// serialize returns a SubcriptionList in OPML format.
func serialize(subscriptions []subcription) string {
var b bytes.Buffer
writer := bufio.NewWriter(&b)
writer.WriteString(xml.Header)
opmlDocument := convertSubscriptionsToOPML(subscriptions)
encoder := xml.NewEncoder(writer)
encoder.Indent("", " ")
if err := encoder.Encode(opmlDocument); err != nil {
slog.Error("Unable to serialize OPML document",
slog.Any("error", err),
)
return ""
}
return b.String()
}
func convertSubscriptionsToOPML(subscriptions []subcription) *opmlDocument {
opmlDocument := &opmlDocument{}
opmlDocument.Version = "2.0"
opmlDocument.Header.Title = "Miniflux"
opmlDocument.Header.DateCreated = time.Now().Format("Mon, 02 Jan 2006 15:04:05 MST")
groupedSubs := groupSubscriptionsByFeed(subscriptions)
categories := make([]string, 0, len(groupedSubs))
for k := range groupedSubs {
categories = append(categories, k)
}
sort.Strings(categories)
for _, categoryName := range categories {
category := opmlOutline{Text: categoryName, Outlines: make(opmlOutlineCollection, 0, len(groupedSubs[categoryName]))}
for _, subscription := range groupedSubs[categoryName] {
category.Outlines = append(category.Outlines, opmlOutline{
Title: subscription.Title,
Text: subscription.Title,
FeedURL: subscription.FeedURL,
SiteURL: subscription.SiteURL,
Description: subscription.Description,
})
}
opmlDocument.Outlines = append(opmlDocument.Outlines, category)
}
return opmlDocument
}
func groupSubscriptionsByFeed(subscriptions []subcription) map[string][]subcription {
groups := make(map[string][]subcription)
for _, subscription := range subscriptions {
groups[subscription.CategoryName] = append(groups[subscription.CategoryName], subscription)
}
return groups
}