|
9 | 9 | using System.Linq; |
10 | 10 | using System.Net; |
11 | 11 | using System.Net.Mail; |
| 12 | +using System.ServiceModel.Syndication; |
12 | 13 | using System.Text; |
13 | 14 | using System.Threading.Tasks; |
14 | 15 | using System.Web; |
|
27 | 28 | using NuGetGallery.Diagnostics; |
28 | 29 | using NuGetGallery.Filters; |
29 | 30 | using NuGetGallery.Helpers; |
| 31 | +using NuGetGallery.Infrastructure; |
30 | 32 | using NuGetGallery.Infrastructure.Lucene; |
31 | 33 | using NuGetGallery.Infrastructure.Mail.Messages; |
32 | 34 | using NuGetGallery.Infrastructure.Mail.Requests; |
@@ -734,6 +736,78 @@ public virtual async Task<ActionResult> DisplayPackage(string id, string version |
734 | 736 | return View(model); |
735 | 737 | } |
736 | 738 |
|
| 739 | + [HttpGet] |
| 740 | + public virtual ActionResult AtomFeed(string id, bool allowPrerelease = false) |
| 741 | + { |
| 742 | + var packageRegistration = _packageService.FindPackageRegistrationById(id); |
| 743 | + if (packageRegistration == null) |
| 744 | + { |
| 745 | + return HttpNotFound(); |
| 746 | + } |
| 747 | + |
| 748 | + var packageVersions = packageRegistration.Packages |
| 749 | + .Where(x => x.Listed && x.PackageStatusKey == PackageStatus.Available) |
| 750 | + .OrderByDescending(p => NuGetVersion.Parse(p.NormalizedVersion)) |
| 751 | + .ToList(); |
| 752 | + |
| 753 | + if (packageVersions.Count == 0) |
| 754 | + { |
| 755 | + return HttpNotFound(); |
| 756 | + } |
| 757 | + |
| 758 | + // most recent version for feed title/description |
| 759 | + var newestVersionPackage = packageVersions.First(); |
| 760 | + |
| 761 | + // the last edited or created package is used as the feed timestamp |
| 762 | + var lastUpdatedPackage = packageVersions.Max(x => x.LastEdited ?? x.Created); |
| 763 | + |
| 764 | + SyndicationFeed feed = new SyndicationFeed() |
| 765 | + { |
| 766 | + Id = Url.Package(packageRegistration.Id, version: null, relativeUrl: false), |
| 767 | + Title = SyndicationContent.CreatePlaintextContent($"{_config.Brand} Feed for {packageRegistration.Id}"), |
| 768 | + Description = SyndicationContent.CreatePlaintextContent(newestVersionPackage.Description), |
| 769 | + LastUpdatedTime = lastUpdatedPackage |
| 770 | + }; |
| 771 | + |
| 772 | + if (!string.IsNullOrWhiteSpace(newestVersionPackage.IconUrl)) |
| 773 | + { |
| 774 | + feed.ImageUrl = new Uri(newestVersionPackage.IconUrl); |
| 775 | + } |
| 776 | + |
| 777 | + List<SyndicationItem> feedItems = new List<SyndicationItem>(); |
| 778 | + |
| 779 | + List<SyndicationPerson> ownersAsAuthors = new List<SyndicationPerson>(); |
| 780 | + foreach (var packageOwner in packageRegistration.Owners) |
| 781 | + { |
| 782 | + ownersAsAuthors.Add(new SyndicationPerson() { Name = packageOwner.Username, Uri = Url.User(packageOwner, relativeUrl: false) }); |
| 783 | + } |
| 784 | + |
| 785 | + foreach (var packageVersion in packageVersions) |
| 786 | + { |
| 787 | + SyndicationItem syndicationItem = new SyndicationItem($"{packageVersion.Id} {packageVersion.Version}", |
| 788 | + packageVersion.Description, |
| 789 | + new Uri(Url.Package(packageRegistration.Id, version: packageVersion.Version, relativeUrl: false))); |
| 790 | + syndicationItem.Id = Url.Package(packageRegistration.Id, version: packageVersion.Version, relativeUrl: false); |
| 791 | + syndicationItem.LastUpdatedTime = packageVersion.LastEdited ?? packageVersion.Created; |
| 792 | + syndicationItem.PublishDate = packageVersion.Created; |
| 793 | + |
| 794 | + syndicationItem.Authors.AddRange(ownersAsAuthors); |
| 795 | + feedItems.Add(syndicationItem); |
| 796 | + } |
| 797 | + |
| 798 | + feed.Items = feedItems; |
| 799 | + |
| 800 | + feed.Links.Add(SyndicationLink.CreateSelfLink( |
| 801 | + new Uri(Url.PackageAtomFeed(packageRegistration.Id, relativeUrl: false)), |
| 802 | + "application/atom+xml")); |
| 803 | + |
| 804 | + feed.Links.Add(SyndicationLink.CreateAlternateLink( |
| 805 | + new Uri(Url.Package(packageRegistration.Id, version: null, relativeUrl: false)), |
| 806 | + "text/html")); |
| 807 | + |
| 808 | + return new SyndicationAtomActionResult(feed); |
| 809 | + } |
| 810 | + |
737 | 811 | [HttpGet] |
738 | 812 | public virtual async Task<ActionResult> License(string id, string version) |
739 | 813 | { |
|
0 commit comments