Files
podcast-search-go/model/podcast.go
malai 1d150111ad feat: Charts 与 LoadFeed 支持 context 透传取消
- 新增 ChartsContext / LoadFeedContext(原方法转发 context.Background(),兼容不变)
- Charts 榜单请求与逐项 lookup 全部改 NewRequestWithContext,循环顶检查
  ctx.Err() 提前中止剩余 lookup
- 修复 resp 在 err 检查前解引用(网络错误/ctx 取消时必 panic)
- 修复 lookup 循环 User-Agent 误设在外层请求上

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 02:02:12 +08:00

126 lines
3.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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秒。
// 需要透传取消时请用 LoadFeedContext。
func LoadFeed(feedURL, proxy string, timeout time.Duration) (*Podcast, error) {
return LoadFeedContext(context.Background(), feedURL, proxy, timeout)
}
// LoadFeedContext 同 LoadFeed但请求生命周期挂在调用方 ctx 上ctx 取消/超时即中断下载。
func LoadFeedContext(ctx context.Context, feedURL, proxy string, timeout time.Duration) (*Podcast, error) {
if timeout <= 0 {
timeout = 30 * time.Second
}
ctx, cancel := context.WithTimeout(ctx, 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
}