119 lines
2.7 KiB
Go
119 lines
2.7 KiB
Go
// Package model 提供播客和剧集的数据模型
|
|
package model
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/mmcdole/gofeed"
|
|
)
|
|
|
|
// Podcast 表示一个播客及其剧集
|
|
type Podcast struct {
|
|
// 播客的唯一标识符
|
|
GUID string `json:"guid,omitempty"`
|
|
|
|
// 播客的URL
|
|
URL string `json:"url,omitempty"`
|
|
|
|
// 播客的链接
|
|
Link string `json:"link,omitempty"`
|
|
|
|
// 播客的标题
|
|
Title string `json:"title,omitempty"`
|
|
|
|
// 播客的描述
|
|
Description string `json:"description,omitempty"`
|
|
|
|
// 播客的图片URL
|
|
Image string `json:"image,omitempty"`
|
|
|
|
// 版权信息
|
|
Copyright string `json:"copyright,omitempty"`
|
|
|
|
// 是否锁定,表示此订阅是否可以被导入到其他平台
|
|
Locked *Locked `json:"locked,omitempty"`
|
|
|
|
// 资金支持信息
|
|
Funding []Funding `json:"funding,omitempty"`
|
|
|
|
// 人员信息
|
|
Persons []Person `json:"persons,omitempty"`
|
|
|
|
// 价值交换信息
|
|
Value []Value `json:"value,omitempty"`
|
|
|
|
// 阻止标签
|
|
Block []Block `json:"block,omitempty"`
|
|
|
|
// 剧集列表
|
|
Episodes []Episode `json:"episodes,omitempty"`
|
|
|
|
// 远程项目
|
|
RemoteItems []RemoteItem `json:"remote_items,omitempty"`
|
|
|
|
// 媒体类型
|
|
Medium Medium `json:"medium,omitempty"`
|
|
}
|
|
|
|
// LoadFeed 从URL加载播客RSS订阅
|
|
func LoadFeed(url string) (*Podcast, error) {
|
|
fp := gofeed.NewParser()
|
|
feed, err := fp.ParseURL(url)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("解析播客订阅失败: %w", err)
|
|
}
|
|
|
|
if feed == nil {
|
|
return nil, errors.New("解析播客订阅失败: 空订阅")
|
|
}
|
|
|
|
podcast := &Podcast{
|
|
Title: feed.Title,
|
|
Description: feed.Description,
|
|
Link: feed.Link,
|
|
Image: feed.Image.URL,
|
|
Copyright: feed.Copyright,
|
|
Episodes: make([]Episode, 0),
|
|
Funding: make([]Funding, 0),
|
|
Persons: make([]Person, 0),
|
|
Value: make([]Value, 0),
|
|
Block: make([]Block, 0),
|
|
Medium: MediumPodcast,
|
|
}
|
|
|
|
// 解析剧集
|
|
for _, item := range feed.Items {
|
|
episode := Episode{
|
|
GUID: item.GUID,
|
|
Title: item.Title,
|
|
Description: item.Description,
|
|
Link: item.Link,
|
|
PublicationDate: item.PublishedParsed,
|
|
Author: item.Author.Name,
|
|
}
|
|
|
|
// 解析媒体URL
|
|
if len(item.Enclosures) > 0 {
|
|
episode.ContentURL = item.Enclosures[0].URL
|
|
}
|
|
|
|
// 解析剧集图片
|
|
if item.Image != nil && item.Image.URL != "" {
|
|
episode.ImageURL = item.Image.URL
|
|
}
|
|
|
|
// 解析时长
|
|
if item.ITunesExt != nil && item.ITunesExt.Duration != "" {
|
|
// 简单处理,实际应该解析时间格式
|
|
durationSec := 0
|
|
fmt.Sscanf(item.ITunesExt.Duration, "%d", &durationSec)
|
|
episode.Duration = durationSec
|
|
}
|
|
|
|
podcast.Episodes = append(podcast.Episodes, episode)
|
|
}
|
|
|
|
return podcast, nil
|
|
}
|