From 48d71b7d6b0ddefdc1db76d5b5f3b3eabc4ae9e4 Mon Sep 17 00:00:00 2001 From: Reo <112817228+reopt999@users.noreply.github.com> Date: Thu, 22 Dec 2022 04:06:26 +0700 Subject: [PATCH] Add Feed for Releases and Tags (#21696) Fixes #19091 Add Feed for Releases and Tags, can be accessed through `reponame/releases.rss`, `reponame/releases.atom`, `reponame/tags.rss`, and `reponame/tags.atom` Signed-off-by: Reo --- options/locale/locale_en-US.ini | 2 ++ routers/web/feed/convert.go | 44 ++++++++++++++++++++++++++++ routers/web/feed/release.go | 50 ++++++++++++++++++++++++++++++++ routers/web/repo/release.go | 25 ++++++++++++++++ routers/web/web.go | 13 +++++++-- templates/repo/release/list.tmpl | 3 ++ 6 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 routers/web/feed/release.go diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index dd31562c3..62471abe6 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2279,6 +2279,8 @@ release.downloads = Downloads release.download_count = Downloads: %s release.add_tag_msg = Use the title and content of release as tag message. release.add_tag = Create Tag Only +release.releases_for = Releases for %s +release.tags_for = Tags for %s branch.name = Branch Name branch.search = Search branches diff --git a/routers/web/feed/convert.go b/routers/web/feed/convert.go index 7d472a7f8..7c375a085 100644 --- a/routers/web/feed/convert.go +++ b/routers/web/feed/convert.go @@ -12,6 +12,7 @@ import ( "strings" activities_model "code.gitea.io/gitea/models/activities" + repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/markup/markdown" @@ -268,3 +269,46 @@ func GetFeedType(name string, req *http.Request) (bool, string, string) { return false, name, "" } + +// feedActionsToFeedItems convert gitea's Repo's Releases to feeds Item +func releasesToFeedItems(ctx *context.Context, releases []*repo_model.Release, isReleasesOnly bool) (items []*feeds.Item, err error) { + for _, rel := range releases { + err := rel.LoadAttributes(ctx) + if err != nil { + return nil, err + } + + var title, content string + + if rel.IsTag { + title = rel.TagName + } else { + title = rel.Title + } + + link := &feeds.Link{Href: rel.HTMLURL()} + content, err = markdown.RenderString(&markup.RenderContext{ + Ctx: ctx, + URLPrefix: rel.Repo.Link(), + Metas: rel.Repo.ComposeMetas(), + }, rel.Note) + + if err != nil { + return nil, err + } + + items = append(items, &feeds.Item{ + Title: title, + Link: link, + Created: rel.CreatedUnix.AsTime(), + Author: &feeds.Author{ + Name: rel.Publisher.DisplayName(), + Email: rel.Publisher.GetEmail(), + }, + Id: fmt.Sprintf("%v: %v", strconv.FormatInt(rel.ID, 10), link.Href), + Content: content, + }) + } + + return items, err +} diff --git a/routers/web/feed/release.go b/routers/web/feed/release.go new file mode 100644 index 000000000..fbfa11c63 --- /dev/null +++ b/routers/web/feed/release.go @@ -0,0 +1,50 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package feed + +import ( + "time" + + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/modules/context" + + "github.com/gorilla/feeds" +) + +// shows tags and/or releases on the repo as RSS / Atom feed +func ShowReleaseFeed(ctx *context.Context, repo *repo_model.Repository, isReleasesOnly bool, formatType string) { + releases, err := repo_model.GetReleasesByRepoID(ctx, ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{ + IncludeTags: !isReleasesOnly, + }) + if err != nil { + ctx.ServerError("GetReleasesByRepoID", err) + return + } + + var title string + var link *feeds.Link + + if isReleasesOnly { + title = ctx.Tr("repo.release.releases_for", repo.FullName()) + link = &feeds.Link{Href: repo.HTMLURL() + "/release"} + } else { + title = ctx.Tr("repo.release.tags_for", repo.FullName()) + link = &feeds.Link{Href: repo.HTMLURL() + "/tags"} + } + + feed := &feeds.Feed{ + Title: title, + Link: link, + Description: repo.Description, + Created: time.Now(), + } + + feed.Items, err = releasesToFeedItems(ctx, releases, isReleasesOnly) + if err != nil { + ctx.ServerError("releasesToFeedItems", err) + return + } + + writeFeed(ctx, feed, formatType) +} diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go index 2047a1cfb..54f503642 100644 --- a/routers/web/repo/release.go +++ b/routers/web/repo/release.go @@ -23,6 +23,7 @@ import ( "code.gitea.io/gitea/modules/upload" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/routers/web/feed" "code.gitea.io/gitea/services/forms" releaseservice "code.gitea.io/gitea/services/release" ) @@ -199,6 +200,30 @@ func releasesOrTags(ctx *context.Context, isTagList bool) { ctx.HTML(http.StatusOK, tplReleases) } +// ReleasesFeedRSS get feeds for releases in RSS format +func ReleasesFeedRSS(ctx *context.Context) { + releasesOrTagsFeed(ctx, true, "rss") +} + +// TagsListFeedRSS get feeds for tags in RSS format +func TagsListFeedRSS(ctx *context.Context) { + releasesOrTagsFeed(ctx, false, "rss") +} + +// ReleasesFeedAtom get feeds for releases in Atom format +func ReleasesFeedAtom(ctx *context.Context) { + releasesOrTagsFeed(ctx, true, "atom") +} + +// TagsListFeedAtom get feeds for tags in RSS format +func TagsListFeedAtom(ctx *context.Context) { + releasesOrTagsFeed(ctx, false, "atom") +} + +func releasesOrTagsFeed(ctx *context.Context, isReleasesOnly bool, formatType string) { + feed.ShowReleaseFeed(ctx, ctx.Repo.Repository, isReleasesOnly, formatType) +} + // SingleRelease renders a single release's page func SingleRelease(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.release.releases") diff --git a/routers/web/web.go b/routers/web/web.go index 20d067a16..31b3eb9ba 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1087,12 +1087,21 @@ func RegisterRoutes(m *web.Route) { // Releases m.Group("/{username}/{reponame}", func() { - m.Get("/tags", repo.TagsList, repo.MustBeNotEmpty, - reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag)) + m.Group("/tags", func() { + m.Get("", repo.TagsList) + m.Get(".rss", feedEnabled, repo.TagsListFeedRSS) + m.Get(".atom", feedEnabled, repo.TagsListFeedAtom) + }, func(ctx *context.Context) { + ctx.Data["EnableFeed"] = setting.EnableFeed + }, repo.MustBeNotEmpty, reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag, true)) m.Group("/releases", func() { m.Get("/", repo.Releases) m.Get("/tag/*", repo.SingleRelease) m.Get("/latest", repo.LatestRelease) + m.Get(".rss", feedEnabled, repo.ReleasesFeedRSS) + m.Get(".atom", feedEnabled, repo.ReleasesFeedAtom) + }, func(ctx *context.Context) { + ctx.Data["EnableFeed"] = setting.EnableFeed }, repo.MustBeNotEmpty, reqRepoReleaseReader, context.RepoRefByType(context.RepoRefTag, true)) m.Get("/releases/attachments/{uuid}", repo.GetAttachment, repo.MustBeNotEmpty, reqRepoReleaseReader) m.Group("/releases", func() { diff --git a/templates/repo/release/list.tmpl b/templates/repo/release/list.tmpl index f8c54bf7f..9f4104bec 100644 --- a/templates/repo/release/list.tmpl +++ b/templates/repo/release/list.tmpl @@ -11,6 +11,9 @@ {{.locale.Tr "repo.release.tags"}} {{end}} + {{if .EnableFeed}} + {{svg "octicon-rss" 18}} + {{end}} {{if (and .CanCreateRelease (not .PageIsTagList))}} {{.locale.Tr "repo.release.new_release"}}