Improve OPML import/export
This commit is contained in:
parent
ace7524905
commit
a76c2a8c22
15 changed files with 51 additions and 31 deletions
|
@ -6,22 +6,27 @@ package errors
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/miniflux/miniflux2/locale"
|
"github.com/miniflux/miniflux2/locale"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// LocalizedError represents an error than could be translated to another language.
|
||||||
type LocalizedError struct {
|
type LocalizedError struct {
|
||||||
message string
|
message string
|
||||||
args []interface{}
|
args []interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Error returns untranslated error message.
|
||||||
func (l LocalizedError) Error() string {
|
func (l LocalizedError) Error() string {
|
||||||
return fmt.Sprintf(l.message, l.args...)
|
return fmt.Sprintf(l.message, l.args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Localize returns the translated error message.
|
||||||
func (l LocalizedError) Localize(translation *locale.Language) string {
|
func (l LocalizedError) Localize(translation *locale.Language) string {
|
||||||
return translation.Get(l.message, l.args...)
|
return translation.Get(l.message, l.args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewLocalizedError returns a new LocalizedError.
|
||||||
func NewLocalizedError(message string, args ...interface{}) LocalizedError {
|
func NewLocalizedError(message string, args ...interface{}) LocalizedError {
|
||||||
return LocalizedError{message: message, args: args}
|
return LocalizedError{message: message, args: args}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// 2017-11-20 13:44:53.735395751 -0800 PST m=+0.047479249
|
// 2017-11-20 14:18:33.283078515 -0800 PST m=+0.039164593
|
||||||
|
|
||||||
package locale
|
package locale
|
||||||
|
|
||||||
|
@ -125,12 +125,13 @@ var Translations = map[string]string{
|
||||||
"Never": "Jamais",
|
"Never": "Jamais",
|
||||||
"Unable to execute request: %v": "Impossible d'exécuter cette requête: %v",
|
"Unable to execute request: %v": "Impossible d'exécuter cette requête: %v",
|
||||||
"Last Parsing Error": "Dernière erreur d'analyse",
|
"Last Parsing Error": "Dernière erreur d'analyse",
|
||||||
"There is a problem with this feed": "Il y a un problème avec cet abonnement"
|
"There is a problem with this feed": "Il y a un problème avec cet abonnement",
|
||||||
|
"Unable to parse OPML file: %v": "Impossible de lire le fichier OPML : %v"
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|
||||||
var TranslationsChecksums = map[string]string{
|
var TranslationsChecksums = map[string]string{
|
||||||
"en_US": "6fe95384260941e8a5a3c695a655a932e0a8a6a572c1e45cb2b1ae8baa01b897",
|
"en_US": "6fe95384260941e8a5a3c695a655a932e0a8a6a572c1e45cb2b1ae8baa01b897",
|
||||||
"fr_FR": "1f75e5a4b581755f7f84687126bc5b96aaf0109a2f83a72a8770c2ad3ddb7ba3",
|
"fr_FR": "8b38f8e33f70c463560b49e7f408509304e4d8f61ae78ca26e33bbba28a9ec76",
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,5 +109,6 @@
|
||||||
"Never": "Jamais",
|
"Never": "Jamais",
|
||||||
"Unable to execute request: %v": "Impossible d'exécuter cette requête: %v",
|
"Unable to execute request: %v": "Impossible d'exécuter cette requête: %v",
|
||||||
"Last Parsing Error": "Dernière erreur d'analyse",
|
"Last Parsing Error": "Dernière erreur d'analyse",
|
||||||
"There is a problem with this feed": "Il y a un problème avec cet abonnement"
|
"There is a problem with this feed": "Il y a un problème avec cet abonnement",
|
||||||
|
"Unable to parse OPML file: %v": "Impossible de lire le fichier OPML : %v"
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,13 @@ package opml
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/miniflux/miniflux2/errors"
|
||||||
"golang.org/x/net/html/charset"
|
"golang.org/x/net/html/charset"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Parse reads an OPML file and returns a SubcriptionList.
|
||||||
func Parse(data io.Reader) (SubcriptionList, error) {
|
func Parse(data io.Reader) (SubcriptionList, error) {
|
||||||
opml := new(Opml)
|
opml := new(Opml)
|
||||||
decoder := xml.NewDecoder(data)
|
decoder := xml.NewDecoder(data)
|
||||||
|
@ -19,7 +20,7 @@ func Parse(data io.Reader) (SubcriptionList, error) {
|
||||||
|
|
||||||
err := decoder.Decode(opml)
|
err := decoder.Decode(opml)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Unable to parse OPML file: %v\n", err)
|
return nil, errors.NewLocalizedError("Unable to parse OPML file: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return opml.Transform(), nil
|
return opml.Transform(), nil
|
||||||
|
|
|
@ -133,6 +133,6 @@ func TestParseInvalidXML(t *testing.T) {
|
||||||
|
|
||||||
_, err := Parse(bytes.NewBufferString(data))
|
_, err := Parse(bytes.NewBufferString(data))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error(err)
|
t.Error("Parse should generate an error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Serialize returns a SubcriptionList in OPML format.
|
||||||
func Serialize(subscriptions SubcriptionList) string {
|
func Serialize(subscriptions SubcriptionList) string {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
writer := bufio.NewWriter(&b)
|
writer := bufio.NewWriter(&b)
|
||||||
|
@ -47,10 +48,6 @@ func groupSubscriptionsByFeed(subscriptions SubcriptionList) map[string]Subcript
|
||||||
groups := make(map[string]SubcriptionList)
|
groups := make(map[string]SubcriptionList)
|
||||||
|
|
||||||
for _, subscription := range subscriptions {
|
for _, subscription := range subscriptions {
|
||||||
// if subs, ok := groups[subscription.CategoryName]; !ok {
|
|
||||||
// groups[subscription.CategoryName] = SubcriptionList{}
|
|
||||||
// }
|
|
||||||
|
|
||||||
groups[subscription.CategoryName] = append(groups[subscription.CategoryName], subscription)
|
groups[subscription.CategoryName] = append(groups[subscription.CategoryName], subscription)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,11 @@
|
||||||
|
|
||||||
package opml
|
package opml
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
import "bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
func TestSerialize(t *testing.T) {
|
func TestSerialize(t *testing.T) {
|
||||||
var subscriptions SubcriptionList
|
var subscriptions SubcriptionList
|
||||||
|
@ -14,6 +17,7 @@ func TestSerialize(t *testing.T) {
|
||||||
subscriptions = append(subscriptions, &Subcription{Title: "Feed 3", FeedURL: "http://example.org/feed/3", SiteURL: "http://example.org/3", CategoryName: "Category 2"})
|
subscriptions = append(subscriptions, &Subcription{Title: "Feed 3", FeedURL: "http://example.org/feed/3", SiteURL: "http://example.org/3", CategoryName: "Category 2"})
|
||||||
|
|
||||||
output := Serialize(subscriptions)
|
output := Serialize(subscriptions)
|
||||||
|
fmt.Println(output)
|
||||||
feeds, err := Parse(bytes.NewBufferString(output))
|
feeds, err := Parse(bytes.NewBufferString(output))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -23,9 +27,16 @@ func TestSerialize(t *testing.T) {
|
||||||
t.Errorf("Wrong number of subscriptions: %d instead of %d", len(feeds), 3)
|
t.Errorf("Wrong number of subscriptions: %d instead of %d", len(feeds), 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(feeds); i++ {
|
found := false
|
||||||
if !feeds[i].Equals(subscriptions[i]) {
|
for _, feed := range feeds {
|
||||||
t.Errorf(`Subscription are different: "%v" vs "%v"`, subscriptions[i], feeds[i])
|
if feed.Title == "Feed 1" && feed.CategoryName == "Category 1" &&
|
||||||
|
feed.FeedURL == "http://example.org/feed/1" && feed.SiteURL == "http://example.org/1" {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
t.Error("Serialized feed is incorrect")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// 2017-11-20 13:44:53.696612572 -0800 PST m=+0.008696070
|
// 2017-11-20 14:18:33.249018092 -0800 PST m=+0.005104170
|
||||||
|
|
||||||
package static
|
package static
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// 2017-11-20 13:44:53.70263347 -0800 PST m=+0.014716968
|
// 2017-11-20 14:18:33.25118969 -0800 PST m=+0.007275768
|
||||||
|
|
||||||
package static
|
package static
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// 2017-11-20 13:44:53.707892515 -0800 PST m=+0.019976013
|
// 2017-11-20 14:18:33.255571671 -0800 PST m=+0.011657749
|
||||||
|
|
||||||
package static
|
package static
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// 2017-11-20 13:44:53.731951822 -0800 PST m=+0.044035320
|
// 2017-11-20 14:18:33.28176883 -0800 PST m=+0.037854908
|
||||||
|
|
||||||
package template
|
package template
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,6 @@ package template
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/miniflux/miniflux2/errors"
|
|
||||||
"github.com/miniflux/miniflux2/locale"
|
|
||||||
"github.com/miniflux/miniflux2/server/route"
|
|
||||||
"github.com/miniflux/miniflux2/server/template/helper"
|
|
||||||
"github.com/miniflux/miniflux2/server/ui/filter"
|
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
@ -18,6 +13,12 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/miniflux/miniflux2/errors"
|
||||||
|
"github.com/miniflux/miniflux2/locale"
|
||||||
|
"github.com/miniflux/miniflux2/server/route"
|
||||||
|
"github.com/miniflux/miniflux2/server/template/helper"
|
||||||
|
"github.com/miniflux/miniflux2/server/ui/filter"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -61,11 +62,13 @@ func (t *TemplateEngine) ParseAll() {
|
||||||
},
|
},
|
||||||
"t": func(key interface{}, args ...interface{}) string {
|
"t": func(key interface{}, args ...interface{}) string {
|
||||||
switch key.(type) {
|
switch key.(type) {
|
||||||
case string, error:
|
case string:
|
||||||
return t.currentLocale.Get(key.(string), args...)
|
return t.currentLocale.Get(key.(string), args...)
|
||||||
case errors.LocalizedError:
|
case errors.LocalizedError:
|
||||||
err := key.(errors.LocalizedError)
|
err := key.(errors.LocalizedError)
|
||||||
return err.Localize(t.currentLocale)
|
return err.Localize(t.currentLocale)
|
||||||
|
case error:
|
||||||
|
return key.(error).Error()
|
||||||
default:
|
default:
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// 2017-11-20 13:44:53.712375345 -0800 PST m=+0.024458843
|
// 2017-11-20 14:18:33.257809595 -0800 PST m=+0.013895673
|
||||||
|
|
||||||
package template
|
package template
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/miniflux/miniflux2/server/core"
|
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
"github.com/miniflux/miniflux2/server/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Controller) Export(ctx *core.Context, request *core.Request, response *core.Response) {
|
func (c *Controller) Export(ctx *core.Context, request *core.Request, response *core.Response) {
|
||||||
|
@ -52,7 +53,7 @@ func (c *Controller) UploadOPML(ctx *core.Context, request *core.Request, respon
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Html().Render("import", args.Merge(tplParams{
|
response.Html().Render("import", args.Merge(tplParams{
|
||||||
"errorMessage": impErr.Error(),
|
"errorMessage": impErr,
|
||||||
"menu": "feeds",
|
"menu": "feeds",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// 2017-11-20 13:44:53.690484632 -0800 PST m=+0.002568130
|
// 2017-11-20 14:18:33.247054842 -0800 PST m=+0.003140920
|
||||||
|
|
||||||
package sql
|
package sql
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue