| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
- // SPDX-License-Identifier: Apache-2.0
- package media // import "miniflux.app/v2/internal/reader/media"
- import (
- "regexp"
- "strconv"
- "strings"
- )
- var textLinkRegex = regexp.MustCompile(`(?mi)(\bhttps?://[^\s]+)`)
- // Specs: https://www.rssboard.org/media-rss
- type MediaItemElement struct {
- MediaCategories MediaCategoryList `xml:"http://search.yahoo.com/mrss/ category"`
- MediaGroups []Group `xml:"http://search.yahoo.com/mrss/ group"`
- MediaContents []Content `xml:"http://search.yahoo.com/mrss/ content"`
- MediaThumbnails []Thumbnail `xml:"http://search.yahoo.com/mrss/ thumbnail"`
- MediaDescriptions DescriptionList `xml:"http://search.yahoo.com/mrss/ description"`
- MediaPeerLinks []PeerLink `xml:"http://search.yahoo.com/mrss/ peerLink"`
- }
- // AllMediaThumbnails returns all thumbnail elements merged together.
- func (e *MediaItemElement) AllMediaThumbnails() []Thumbnail {
- items := make([]Thumbnail, 0, len(e.MediaThumbnails)+len(e.MediaGroups))
- items = append(items, e.MediaThumbnails...)
- for _, mediaGroup := range e.MediaGroups {
- items = append(items, mediaGroup.MediaThumbnails...)
- }
- return items
- }
- // AllMediaContents returns all content elements merged together.
- func (e *MediaItemElement) AllMediaContents() []Content {
- items := make([]Content, 0, len(e.MediaContents)+len(e.MediaGroups))
- items = append(items, e.MediaContents...)
- for _, mediaGroup := range e.MediaGroups {
- items = append(items, mediaGroup.MediaContents...)
- }
- return items
- }
- // AllMediaPeerLinks returns all peer link elements merged together.
- func (e *MediaItemElement) AllMediaPeerLinks() []PeerLink {
- items := make([]PeerLink, 0, len(e.MediaPeerLinks)+len(e.MediaGroups))
- items = append(items, e.MediaPeerLinks...)
- for _, mediaGroup := range e.MediaGroups {
- items = append(items, mediaGroup.MediaPeerLinks...)
- }
- return items
- }
- // FirstMediaDescription returns the first description element.
- func (e *MediaItemElement) FirstMediaDescription() string {
- description := e.MediaDescriptions.First()
- if description != "" {
- return description
- }
- for _, mediaGroup := range e.MediaGroups {
- description = mediaGroup.MediaDescriptions.First()
- if description != "" {
- return description
- }
- }
- return ""
- }
- // Group represents a XML element "media:group".
- type Group struct {
- MediaContents []Content `xml:"http://search.yahoo.com/mrss/ content"`
- MediaThumbnails []Thumbnail `xml:"http://search.yahoo.com/mrss/ thumbnail"`
- MediaDescriptions DescriptionList `xml:"http://search.yahoo.com/mrss/ description"`
- MediaPeerLinks []PeerLink `xml:"http://search.yahoo.com/mrss/ peerLink"`
- }
- // Content represents a XML element "media:content".
- type Content struct {
- URL string `xml:"url,attr"`
- Type string `xml:"type,attr"`
- FileSize string `xml:"fileSize,attr"`
- Medium string `xml:"medium,attr"`
- }
- // MimeType returns the attachment mime type.
- func (mc *Content) MimeType() string {
- if mc.Type != "" {
- return mc.Type
- }
- switch mc.Medium {
- case "image":
- return "image/*"
- case "video":
- return "video/*"
- case "audio":
- return "audio/*"
- default:
- return "application/octet-stream"
- }
- }
- // Size returns the attachment size.
- func (mc *Content) Size() int64 {
- size, _ := strconv.ParseInt(mc.FileSize, 10, 0)
- return size
- }
- // Thumbnail represents a XML element "media:thumbnail".
- type Thumbnail struct {
- URL string `xml:"url,attr"`
- }
- // MimeType returns the attachment mime type.
- func (t *Thumbnail) MimeType() string {
- return "image/*"
- }
- // Size returns the attachment size.
- func (t *Thumbnail) Size() int64 {
- return 0
- }
- // PeerLink represents a XML element "media:peerLink".
- type PeerLink struct {
- URL string `xml:"href,attr"`
- Type string `xml:"type,attr"`
- }
- // MimeType returns the attachment mime type.
- func (p *PeerLink) MimeType() string {
- if p.Type != "" {
- return p.Type
- }
- return "application/octet-stream"
- }
- // Size returns the attachment size.
- func (p *PeerLink) Size() int64 {
- return 0
- }
- // Description represents a XML element "media:description".
- type Description struct {
- Type string `xml:"type,attr"`
- Description string `xml:",chardata"`
- }
- // HTML returns the description as HTML.
- func (d *Description) HTML() string {
- if d.Type == "html" {
- return d.Description
- }
- content := textLinkRegex.ReplaceAllString(d.Description, `<a href="${1}">${1}</a>`)
- return strings.ReplaceAll(content, "\n", "<br>")
- }
- // DescriptionList represents a list of "media:description" XML elements.
- type DescriptionList []Description
- // First returns the first non-empty description.
- func (dl DescriptionList) First() string {
- for _, description := range dl {
- contents := description.HTML()
- if contents != "" {
- return contents
- }
- }
- return ""
- }
- type MediaCategoryList []MediaCategory
- func (mcl MediaCategoryList) Labels() []string {
- var labels []string
- for _, category := range mcl {
- label := strings.TrimSpace(category.Label)
- if label != "" {
- labels = append(labels, label)
- }
- }
- return labels
- }
- type MediaCategory struct {
- Label string `xml:"label,attr"`
- }
|