diff --git a/go.mod b/go.mod index f30c5de..9eae563 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.18 require ( git.sr.ht/~adnano/go-gemini v0.2.3 github.com/flosch/pongo2/v6 v6.0.0 + github.com/gorilla/feeds v1.1.1 google.golang.org/grpc v1.48.0 google.golang.org/protobuf v1.28.1 ) diff --git a/go.sum b/go.sum index 9f031c1..b8148c8 100644 --- a/go.sum +++ b/go.sum @@ -48,11 +48,11 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/feeds v1.1.1 h1:HwKXxqzcRNg9to+BbvJog4+f3s/xzvtZXICcQGutYfY= +github.com/gorilla/feeds v1.1.1/go.mod h1:Nk0jZrvPFZX1OBe5NPiddPw7CfwF6Q9eqzaBbaightA= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/n0x1m/md2gmi v1.0.0 h1:T4FTIjojSutOvyh7okIO7N59sk7KD9XyQMx35JX5jjA= -github.com/n0x1m/md2gmi v1.0.0/go.mod h1:q5iY7/I5QlC5bUrqmkXVA2FR2HOB9+PmqDhpCNHF/vc= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= diff --git a/main.go b/main.go index 93f90d3..97ce560 100644 --- a/main.go +++ b/main.go @@ -13,6 +13,7 @@ import ( "git.sr.ht/~adnano/go-gemini" "git.sr.ht/~adnano/go-gemini/certificate" "github.com/flosch/pongo2/v6" + "github.com/gorilla/feeds" "google.golang.org/grpc" ) @@ -64,6 +65,8 @@ func main() { } func processRebuild(ctx context.Context, w gemini.ResponseWriter, r *gemini.Request) { + log.Println("REBUILD") + q, err := gemini.QueryUnescape(r.URL.RawQuery) if err != nil || q != key { w.WriteHeader(gemini.StatusServerUnavailable, "Don't wake up the dragons :-*") @@ -86,6 +89,7 @@ func processRebuild(ctx context.Context, w gemini.ResponseWriter, r *gemini.Requ if err != nil { w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error") } + log.Println("REBUILD: success") } else { w.WriteHeader(gemini.StatusNotFound, "Out of space") } @@ -121,6 +125,8 @@ func process(_ context.Context, w gemini.ResponseWriter, r *gemini.Request) { w.WriteHeader(gemini.StatusPermanentRedirect, "/sgs") case regexp.MustCompile(`^/(sgs|en)/?$`).MatchString(r.URL.Path): renderIndex(lang, w, client) + case regexp.MustCompile(`^/(sgs|en)/atom.xml$`).MatchString(r.URL.Path): + renderFeed(lang, w, r, client) case regexp.MustCompile(`^/(sgs|en)/a/?$`).MatchString(r.URL.Path): renderAbout(lang, w) case regexp.MustCompile(`^/(sgs|en)/s/?$`).MatchString(r.URL.Path): @@ -168,6 +174,71 @@ func renderIndex(lang string, w gemini.ResponseWriter, client TreeManagerClient) } } +func renderFeed(lang string, w gemini.ResponseWriter, r *gemini.Request, client TreeManagerClient) { + langFilter := TreeRequest_Filter{Key: "lang", Value: lang} + filters := []*TreeRequest_Filter{&langFilter} + + path := "" + tr := TreeRequest{Path: &path, Filter: filters} + + tree, err := client.GetSummery(context.Background(), &tr) + if err != nil { + w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error") + return + } + + w.SetMediaType("application/atom+xml") + now := time.Now() + language := "Samogitian" + if lang == "en" { + language = "English" + } + feed := &feeds.Feed{ + Title: "\U0001F31B Arna alkierios [" + lang + "]", + Link: &feeds.Link{Href: "gemini://arns.lt/" + lang}, + Description: "personal gemini capsule by Arns Udovič [" + language + " version]", + Author: &feeds.Author{Name: "Arns Udovič", Email: "zordsdavini@arns.lt"}, + Created: now, + } + for _, file := range GetLastFiles(tree.Files) { + created, err := time.Parse("2006-01-02", file.Created) + if err != nil { + created = time.Now() + } + feed.Add( + &feeds.Item{ + Title: file.Description, + Link: &feeds.Link{Href: fmt.Sprintf("gemini://%s/%s/f%s/%s/%s", + r.URL.Host, + lang, + file.CategoryPath(), + file.Id, + file.GmiName(), + )}, + Description: fmt.Sprintf("%s %s [%s]", + file.Description, + file.CategoryPath(), + strings.Join(file.Tags, ","), + ), + Author: &feeds.Author{Name: "Arns Udovič", Email: "zordsdavini@arns.lt"}, + Created: created, + }, + ) + } + + atom, err := feed.ToAtom() + if err != nil { + w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error") + return + } + + _, err = w.Write([]byte(atom)) + if err != nil { + w.WriteHeader(gemini.StatusTemporaryFailure, "Internal server error") + return + } +} + func renderAbout(lang string, w gemini.ResponseWriter) { w.SetMediaType("text/gemini") tpl := pongo2.Must(pongo2.FromFile(fmt.Sprintf("templates/%s/about.gmi", lang)))