/// <summary> /// Create a syndication feed from a list of page /// </summary> /// <param name="session">a session</param> /// <param name="pages">the pages</param> /// <param name="maxBlocks">limits the parsing of each page to the 1st 20 blocks. Max value: 100</param> /// <param name="stopBeforeFirstSubHeader">when true, stop parsing a page when a line containing a sub_header is found</param> /// <param name="cancel"></param> /// <returns>A SyndicationFeed containing one SyndicationItem per page</returns> /// <remarks> /// The created feed has no title/description /// </remarks> public static async Task<SyndicationFeed> GetSyndicationFeed(this NotionSession session, IEnumerable<Guid> pages, int maxBlocks = 20, bool stopBeforeFirstSubHeader = true, CancellationToken cancel = default) { //notion's limitation if (maxBlocks > 100) throw new ArgumentOutOfRangeException(nameof(maxBlocks)); var feedItems = new List<SyndicationItem>(); foreach (var pageId in pages) { //get blocks and extract an html content var chunks = await session.LoadPageChunk(pageId, 0, maxBlocks, cancel); var pageBlock = chunks.RecordMap.Block[pageId]; //collection_view_page not supported if (pageBlock.Permissions?.Any(p => p.Role == Permission.RoleReader && p.Type == Permission.TypePublic) == true && pageBlock.Type == "page") { //var content = chunks.RecordMap.GetHtmlAbstract(pageId); var content = chunks.RecordMap.GetHtml(pageId, throwIfBlockMissing: false, stopBeforeFirstSubHeader: stopBeforeFirstSubHeader, throwIfCantDecodeTextData: false); var pageUri = NotionUtils.GetPageUri(pageId, pageBlock.Title); var item = new SyndicationItem(pageBlock.Title, content, pageUri) { Id = pageId.ToString("N"), BaseUri = pageUri, Summary = new TextSyndicationContent(content), PublishDate = pageBlock.CreatedTime.EpochToDateTimeOffset(), LastUpdatedTime = pageBlock.LastEditedTime.EpochToDateTimeOffset(), }; if (!String.IsNullOrWhiteSpace(pageBlock.Format?.PageIcon)) { if(Uri.TryCreate(pageBlock.Format.PageIcon, UriKind.Absolute, out _)) item.AttributeExtensions.Add(new XmlQualifiedName("iconUrl"), pageBlock.Format.PageIcon); else item.AttributeExtensions.Add(new XmlQualifiedName("iconString"), pageBlock.Format.PageIcon); } feedItems.Add(item); } } var feed = new SyndicationFeed(feedItems) { LastUpdatedTime = feedItems.DefaultIfEmpty().Max(item => item?.LastUpdatedTime ?? DateTimeOffset.MinValue), //Copyright = }; return feed; }