コード例 #1
0
        public StructureRss(Logger logger, string dbUrl)
        {
            this.logger = logger;

            // API only available to authenticated users
            BeforeAsync = async(p, c) => await c.EnsureIsAuthenticatedAsync();

            var cache = new Utils.Cache <List <Rss> >(400, TimeSpan.FromMinutes(20), async(string key) =>
            {
                logger.Log(LogLevel.Info, $"Load RSS: {key}");
                var items = new List <Rss>();
                try
                {
                    var settings = new XmlReaderSettings
                    {
                        IgnoreComments = true,
                        DtdProcessing  = DtdProcessing.Ignore
                    };
                    var uri       = new Uri(key);
                    var doc       = await LoadXmlAsync(uri);
                    XElement root = doc.Root;
                    XNamespace ns = doc.Root.Name.Namespace;
                    var contentns = "http://purl.org/rss/1.0/modules/content/";
                    var dcns      = "http://purl.org/dc/elements/1.1/";

                    // RSS 2.0
                    if (root.Name.LocalName == "rss")
                    {
                        foreach (XElement item in root.Element("channel").Elements("item"))
                        {
                            var rss   = new Rss();
                            var title = item.Element("title");
                            if (title != null)
                            {
                                rss.title = title.Value;
                            }
                            var content = item.Element("description");
                            if (content != null)
                            {
                                rss.content = content.Value;
                            }
                            var link = item.Element("link");
                            if (link != null)
                            {
                                rss.link = link.Value;
                            }
                            var date = item.Element("pubDate");
                            if (date == null)
                            {
                                date = item.Element(XName.Get("date", dcns));
                            }
                            if (date != null)
                            {
                                rss.pubDate = DateTime.Parse(date.Value);
                            }
                            var encoded = item.Element(XName.Get("encoded", contentns));
                            if (encoded != null)
                            {
                                var imageUrl = GetImageFromHtml(encoded.Value);
                                if (imageUrl != null)
                                {
                                    rss.image = imageUrl;
                                }
                            }
                            items.Add(rss);
                        }
                    }
                    // ATOM
                    else if (root.Name.LocalName == "feed")
                    {
                        var atomns = "http://www.w3.org/2005/Atom";
                        foreach (XElement item in root.Elements(XName.Get("entry", atomns)))
                        {
                            var rss   = new Rss();
                            var title = item.Element(XName.Get("title", atomns));
                            if (title != null)
                            {
                                rss.title = title.Value;
                            }
                            var summary = item.Element(XName.Get("summary", atomns));
                            if (summary != null)
                            {
                                rss.content = summary.Value;
                            }
                            var content = item.Element(XName.Get("content", atomns));
                            if (content != null)
                            {
                                var type = "text";
                                if (content.Attribute("type") != null)
                                {
                                    type = content.Attribute("type").Value;
                                }
                                var textContent = content.Value;
                                if (type == "html")
                                {
                                    textContent  = GetTextFromHtml(content.Value);
                                    var imageUrl = GetImageFromHtml(content.Value);
                                    if (imageUrl != null)
                                    {
                                        rss.image = imageUrl;
                                    }
                                }
                                if (rss.content == null)
                                {
                                    rss.content = textContent;
                                }
                            }
                            var link = item.Element(XName.Get("link", atomns));
                            if (link != null)
                            {
                                rss.link = link.Attribute("href").Value;
                            }
                            var updated = item.Element(XName.Get("updated", atomns));
                            if (updated != null)
                            {
                                rss.pubDate = DateTime.Parse(updated.Value);
                            }
                            items.Add(rss);
                        }
                    }
                    // RSS 1.0
                    else if (root.Name.LocalName == "RDF")
                    {
                        var rss10ns = "http://purl.org/rss/1.0/";

                        foreach (XElement item in root.Elements(XName.Get("item", rss10ns)))
                        {
                            var rss   = new Rss();
                            var title = item.Element(XName.Get("title", rss10ns));
                            if (title != null)
                            {
                                rss.title = title.Value;
                            }
                            var content = item.Element(XName.Get("description", rss10ns));
                            if (content != null)
                            {
                                rss.content = content.Value;
                            }
                            var link = item.Element(XName.Get("link", rss10ns));
                            if (link != null)
                            {
                                rss.link = link.Value;
                            }
                            var date = item.Element(XName.Get("date", dcns));
                            if (date != null)
                            {
                                rss.pubDate = DateTime.Parse(date.Value);
                            }
                            var encoded = item.Element(XName.Get("encoded", contentns));
                            if (encoded != null)
                            {
                                var imageUrl = GetImageFromHtml(encoded.Value);
                                if (imageUrl != null)
                                {
                                    rss.image = imageUrl;
                                }
                            }
                            items.Add(rss);
                        }
                    }
                }
                catch (Exception e)
                {
                    logger.Log(LogLevel.Error, $"invalid RSS feed '{key}'. Exception: {e}");
                    items = null;
                }
                return(items);
            }, true);


            GetAsync["/{uai}/rss"] = async(p, c) =>
            {
                var structure = new Structure {
                    id = (string)p["uai"]
                };
                using (DB db = await DB.CreateAsync(dbUrl))
                {
                    if (await structure.LoadAsync(db))
                    {
                        await c.EnsureHasRightsOnStructureAsync(structure, true, false, false);

                        await structure.LoadExpandFieldAsync(db, nameof(structure.flux));

                        var infos = new ModelList <Rss>();
                        // parallel loading
                        var tasks = structure.flux.Select((flux) => cache.GetAsync(flux.url));
                        await Task.WhenAll(tasks);

                        tasks.ForEach((t) => { if (t.Result != null)
                                               {
                                                   infos.AddRange(t.Result);
                                               }
                                      });

                        c.Response.StatusCode = 200;
                        c.Response.Content    = infos.Filter(c);
                    }
                }
            };
        }