generated by Claude-3.7-Sonnet

This commit is contained in:
2025-03-28 22:27:08 +08:00
commit fdde34e1f0
13 changed files with 1581 additions and 0 deletions

40
model/apple_podcast.go Normal file
View File

@@ -0,0 +1,40 @@
// Package model 提供播客和剧集的数据模型
package model
import (
"time"
)
// Podcast 表示从Apple Podcasts API获取的播客信息
type ApplePodcast struct {
WrapperType string `json:"wrapperType,omitempty"`
Kind string `json:"kind,omitempty"`
CollectionID int `json:"collectionId,omitempty"`
TrackID int `json:"trackId,omitempty"`
ArtistName string `json:"artistName,omitempty"`
CollectionName string `json:"collectionName,omitempty"`
TrackName string `json:"trackName,omitempty"`
CollectionCensoredName string `json:"collectionCensoredName,omitempty"`
TrackCensoredName string `json:"trackCensoredName,omitempty"`
CollectionViewURL string `json:"collectionViewUrl,omitempty"`
FeedURL string `json:"feedUrl,omitempty"`
TrackViewURL string `json:"trackViewUrl,omitempty"`
ArtworkURL30 string `json:"artworkUrl30,omitempty"`
ArtworkURL60 string `json:"artworkUrl60,omitempty"`
ArtworkURL100 string `json:"artworkUrl100,omitempty"`
CollectionPrice float64 `json:"collectionPrice,omitempty"`
TrackPrice float64 `json:"trackPrice,omitempty"`
CollectionHDPrice float64 `json:"collectionHdPrice,omitempty"`
ReleaseDate time.Time `json:"releaseDate,omitempty"`
CollectionExplicitness string `json:"collectionExplicitness,omitempty"`
TrackExplicitness string `json:"trackExplicitness,omitempty"`
TrackCount int `json:"trackCount,omitempty"`
TrackTimeMillis int `json:"trackTimeMillis,omitempty"`
Country string `json:"country,omitempty"`
Currency string `json:"currency,omitempty"`
PrimaryGenreName string `json:"primaryGenreName,omitempty"`
ContentAdvisoryRating string `json:"contentAdvisoryRating,omitempty"`
ArtworkURL600 string `json:"artworkUrl600,omitempty"`
GenreIDs []string `json:"genreIds,omitempty"`
Genres []string `json:"genres,omitempty"`
}

118
model/podcast.go Normal file
View File

@@ -0,0 +1,118 @@
// 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
}

45
model/search.go Normal file
View File

@@ -0,0 +1,45 @@
// Package model 提供播客和剧集的数据模型
package model
import (
"time"
)
// Item 表示搜索结果中的一个播客项目
type Item struct {
// 播客的集合ID
CollectionID int `json:"collectionId,omitempty"`
// 播客的标题
Title string `json:"title,omitempty"`
// 播客的作者
Author string `json:"author,omitempty"`
// 播客的Feed URL
FeedURL string `json:"feedUrl,omitempty"`
// 播客的小尺寸封面图URL
ArtworkURL string `json:"artworkUrl,omitempty"`
// 播客的大尺寸封面图URL
ArtworkURL600 string `json:"artworkUrl600,omitempty"`
// 播客的流派
Genres []string `json:"genres,omitempty"`
}
// SearchResult 表示播客搜索的结果
type SearchResult struct {
// 结果数量
ResultCount int `json:"resultCount,omitempty"`
// 搜索是否成功
Successful bool `json:"successful,omitempty"`
// 搜索结果项目列表
Items []Item `json:"items,omitempty"`
// 处理时间
ProcessedTime time.Time `json:"processedTime,omitempty"`
}

57
model/transcript.go Normal file
View File

@@ -0,0 +1,57 @@
// Package model 提供播客和剧集的数据模型
package model
import (
"time"
)
// TranscriptFormat 表示转录文件的格式
type TranscriptFormat string
const (
// TranscriptFormatJSON 表示JSON格式的转录
TranscriptFormatJSON TranscriptFormat = "json"
// TranscriptFormatSubrip 表示SRT格式的转录
TranscriptFormatSubrip TranscriptFormat = "subrip"
// TranscriptFormatUnsupported 表示不支持的格式
TranscriptFormatUnsupported TranscriptFormat = "unsupported"
)
// TranscriptURL 表示播客中包含的转录URL
type TranscriptURL struct {
// 转录的URL
URL string `json:"url,omitempty"`
// 转录的类型json或srt
Type TranscriptFormat `json:"type,omitempty"`
// 转录的语言
Language string `json:"language,omitempty"`
// 如果设置为captions表示这是一个闭合字幕文件
Rel string `json:"rel,omitempty"`
}
// Transcript 表示一个转录
type Transcript struct {
// 字幕列表
Subtitles []Subtitle `json:"subtitles,omitempty"`
}
// Subtitle 表示转录中的一行
type Subtitle struct {
// 字幕的索引(顺序)
Index int `json:"index,omitempty"`
// 字幕的开始时间
Start time.Duration `json:"start,omitempty"`
// 字幕的结束时间
End time.Duration `json:"end,omitempty"`
// 字幕的文本内容
Data string `json:"data,omitempty"`
// 发言人(可选)
Speaker string `json:"speaker,omitempty"`
}

150
model/types.go Normal file
View File

@@ -0,0 +1,150 @@
// Package model 提供播客和剧集的数据模型
package model
import (
"time"
)
// Medium 表示媒体类型
type Medium string
const (
// MediumPodcast 表示播客媒体类型
MediumPodcast Medium = "podcast"
// MediumMusic 表示音乐媒体类型
MediumMusic Medium = "music"
// MediumAudiobook 表示有声书媒体类型
MediumAudiobook Medium = "audiobook"
)
// Locked 表示播客是否锁定
type Locked struct {
// 是否锁定
Locked bool `json:"locked,omitempty"`
// 锁定的所有者
Owner string `json:"owner,omitempty"`
}
// Funding 表示资金支持信息
type Funding struct {
// 资金支持URL
URL string `json:"url,omitempty"`
// 资金支持文本
Text string `json:"text,omitempty"`
}
// Person 表示人员信息
type Person struct {
// 人员名称
Name string `json:"name,omitempty"`
// 人员角色
Role string `json:"role,omitempty"`
// 人员组
Group string `json:"group,omitempty"`
// 人员头像URL
Img string `json:"img,omitempty"`
// 人员URL
Href string `json:"href,omitempty"`
}
// Value 表示价值交换信息
type Value struct {
// 类型
Type string `json:"type,omitempty"`
// 方法
Method string `json:"method,omitempty"`
// 建议
Suggested string `json:"suggested,omitempty"`
// 接收者
Recipients []ValueRecipient `json:"recipients,omitempty"`
}
// ValueRecipient 表示价值接收者
type ValueRecipient struct {
// 名称
Name string `json:"name,omitempty"`
// 类型
Type string `json:"type,omitempty"`
// 地址
Address string `json:"address,omitempty"`
// 分割
Split float64 `json:"split,omitempty"`
// 自定义键
CustomKey string `json:"customKey,omitempty"`
// 自定义值
CustomValue string `json:"customValue,omitempty"`
}
// Block 表示阻止标签
type Block struct {
// 阻止的ID
ID string `json:"id,omitempty"`
// 阻止的URL
URL string `json:"url,omitempty"`
}
// Episode 表示播客剧集
type Episode struct {
// 剧集的唯一标识符
GUID string `json:"guid,omitempty"`
// 剧集的标题
Title string `json:"title,omitempty"`
// 剧集的描述
Description string `json:"description,omitempty"`
// 剧集的链接
Link string `json:"link,omitempty"`
// 剧集的发布日期
PublicationDate *time.Time `json:"publicationDate,omitempty"`
// 剧集的作者
Author string `json:"author,omitempty"`
// 剧集的内容URL
ContentURL string `json:"contentUrl,omitempty"`
// 剧集的图片URL
ImageURL string `json:"imageUrl,omitempty"`
// 剧集的时长(秒)
Duration int `json:"duration,omitempty"`
// 剧集的转录URL列表
TranscriptURLs []TranscriptURL `json:"transcriptUrls,omitempty"`
}
// RemoteItem 表示远程项目
type RemoteItem struct {
// 远程项目的唯一标识符
GUID string `json:"guid,omitempty"`
// 远程项目的标题
Title string `json:"title,omitempty"`
// 远程项目的描述
Description string `json:"description,omitempty"`
// 远程项目的链接
Link string `json:"link,omitempty"`
// 远程项目的发布日期
PublicationDate *time.Time `json:"publicationDate,omitempty"`
// 远程项目的作者
Author string `json:"author,omitempty"`
// 远程项目的内容URL
ContentURL string `json:"contentUrl,omitempty"`
// 远程项目的图片URL
ImageURL string `json:"imageUrl,omitempty"`
// 远程项目的时长(秒)
Duration int `json:"duration,omitempty"`
// 远程项目的转录URL列表
TranscriptURLs []TranscriptURL `json:"transcriptUrls,omitempty"`
}