120 lines
2.7 KiB
Go
120 lines
2.7 KiB
Go
// Package model 提供播客和剧集的数据模型
|
||
package model
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"net/http"
|
||
"net/url"
|
||
"time"
|
||
|
||
"github.com/mmcdole/gofeed"
|
||
"github.com/sirupsen/logrus"
|
||
)
|
||
|
||
// 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"`
|
||
|
||
// 语言
|
||
Language string `json:"language,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 []*gofeed.Item `json:"episodes,omitempty"`
|
||
|
||
// 远程项目
|
||
RemoteItems []RemoteItem `json:"remote_items,omitempty"`
|
||
|
||
// 媒体类型
|
||
Medium Medium `json:"medium,omitempty"`
|
||
}
|
||
|
||
// LoadFeed 从URL加载播客RSS订阅,timeout为超时时间,如果timeout<=0则使用默认值30秒
|
||
func LoadFeed(feedURL, proxy string, timeout time.Duration) (*Podcast, error) {
|
||
if timeout <= 0 {
|
||
timeout = 30 * time.Second
|
||
}
|
||
|
||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||
defer cancel()
|
||
|
||
fp := gofeed.NewParser()
|
||
fp.UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
|
||
|
||
fp.Client = &http.Client{}
|
||
// setup proxy
|
||
if proxy != "" {
|
||
proxyURL, err := url.Parse(proxy)
|
||
if err != nil {
|
||
logrus.WithError(err).Errorf("Failed to parse proxy url: %s", proxy)
|
||
return nil, err
|
||
}
|
||
fp.Client = &http.Client{
|
||
Transport: &http.Transport{
|
||
Proxy: http.ProxyURL(proxyURL),
|
||
},
|
||
}
|
||
logrus.Infof("Using proxy: %s", proxy)
|
||
}
|
||
|
||
feed, err := fp.ParseURLWithContext(feedURL, ctx)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("解析播客订阅失败: %w", err)
|
||
}
|
||
|
||
imageURL := ""
|
||
if feed.Image != nil {
|
||
imageURL = feed.Image.URL
|
||
}
|
||
podcast := &Podcast{
|
||
Title: feed.Title,
|
||
Description: feed.Description,
|
||
Link: feed.Link,
|
||
Image: imageURL,
|
||
Copyright: feed.Copyright,
|
||
Language: feed.Language,
|
||
Episodes: feed.Items,
|
||
Funding: make([]Funding, 0),
|
||
Persons: make([]Person, 0),
|
||
Value: make([]Value, 0),
|
||
Block: make([]Block, 0),
|
||
Medium: MediumPodcast,
|
||
}
|
||
|
||
return podcast, nil
|
||
}
|