Documentation
¶
Index ¶
- Constants
- Variables
- func Download(ctx context.Context, wg *sync.WaitGroup, prog *Prog) (err error)
- func GetRadikronPath(path string) (string, error)
- func InitSemaphores(asset *Asset)
- func NewOutputConfig(fileBaseName, fileFormat, downloadDir, folder string) (*radigo.OutputConfig, error)
- type Area
- type Asset
- func (a *Asset) AddExtraStations(es []string)
- func (a *Asset) GenerateGPSForAreaID(areaID string) string
- func (a *Asset) GetAreaIDByStationID(stationID string) string
- func (a *Asset) GetPartialKey(offset, length int64) (string, error)
- func (a *Asset) GetStationIDsByAreaID(areaID string) []string
- func (a *Asset) LoadAvailableStations(areaID string)
- func (a *Asset) NewDevice(ctx context.Context, areaID string) (*Device, error)
- func (a *Asset) RemoveIgnoreStations(is []string)
- func (a *Asset) UnmarshalJSON(b []byte) error
- type ContextKey
- type Coordinate
- type Coordinates
- type Device
- type Devices
- type EventEmitter
- type Prog
- type ProgGenre
- type Progs
- type Regions
- type Rule
- func (r *Rule) HasDoW() bool
- func (r *Rule) HasKeyword() bool
- func (r *Rule) HasPfm() bool
- func (r *Rule) HasStationID() bool
- func (r *Rule) HasTitle() bool
- func (r *Rule) HasWindow() bool
- func (r *Rule) Match(stationID string, p *Prog) bool
- func (r *Rule) MatchDoW(ft string) bool
- func (r *Rule) MatchKeyword(p *Prog) bool
- func (r *Rule) MatchPfm(pfm string) bool
- func (r *Rule) MatchSilent(stationID string, p *Prog) bool
- func (r *Rule) MatchStationID(stationID string) bool
- func (r *Rule) MatchTitle(title string) bool
- func (r *Rule) MatchWindow(ft string) bool
- func (r *Rule) SetName(name string)
- type Rules
- func (rs Rules) FindMatch(stationID string, p *Prog) *Rule
- func (rs Rules) FindMatchSilent(stationID string, p *Prog) *Rule
- func (rs Rules) HasMatch(stationID string, p *Prog) bool
- func (rs Rules) HasRuleForStationID(stationID string) bool
- func (rs Rules) HasRuleWithCriteria() bool
- func (rs Rules) HasRuleWithoutStationID() bool
- type SDK
- type Schedules
- type Station
- type Stations
- type Versions
- type XMLProg
- type XMLProgItem
- type XMLProgs
- type XMLRegion
- type XMLRegionStation
- type XMLRegionStations
- type XMLWeekly
- type XMLWeeklyStation
Constants ¶
const ( // BufferMinutes for fetching the playlist.m3u8 chunks BufferMinutes = 5 // DatetimeLayout for time strings from radiko DatetimeLayout = "20060102150405" // DefaultArea for radiko are DefaultArea = "JP13" // RetryDelaySecond for initial delay DefaultInitialDelaySeconds = 60 // DefaultInterval to fetch the programs DefaultInterval = "168h" // DefaultMinimumOutputSize DefaultMinimumOutputSize = 1 // Language for ID3v2 tags ID3v2LangJPN = "jpn" // LatLng for Japan JapanLatLng = 40.0 // Kilobytes for the metric bytes Kilobytes = 1024 // MaxDownloadingConcurrency limits concurrent download operations MaxDownloadingConcurrency = 64 // MaxEncodingConcurrency limits concurrent encoding operations (MP3 conversion) // Set lower than MaxDownloadingConcurrency since encoding is CPU-intensive MaxEncodingConcurrency = 2 // MaxRetryAttempts for BackOffDelay MaxRetryAttempts = 8 // OneDay is 24 hours OneDay = 24 // OutputDatetimeLayout for downloaded files OutputDatetimeLayout = "2006-01-02-1504" // TZTokyo for time location TZTokyo = "Asia/Tokyo" // UserIDLength for user-id UserIDLength = 16 // PlaylistM3U8Length parameter for m3u8 playlist requests PlaylistM3U8Length = "15" // DirPermissions for directory creation (0755 = rwxr-xr-x) DirPermissions = 0755 // API endpoints // region full APIRegionFull = "https://radiko.jp/v3/station/region/full.xml" APIPlaylistM3U8 = "https://radiko.jp/v2/api/ts/playlist.m3u8" APIWeeklyProgram = "https://radiko.jp/v3/program/station/weekly/%s.xml" // HTTP Headers // auth1 req UserAgentHeader = "User-Agent" RadikoAreaIDHeader = "X-Radiko-AreaId" RadikoAppHeader = "X-Radiko-App" RadikoAppVersionHeader = "X-Radiko-App-Version" RadikoDeviceHeader = "X-Radiko-Device" RadikoUserHeader = "X-Radiko-User" // auth1 res RadikoAuthTokenHeader = "X-Radiko-AuthToken" //nolint:gosec RadikoKeyLengthHeader = "X-Radiko-KeyLength" RadikoKeyOffsetHeader = "X-Radiko-KeyOffset" // auth2 req RadikoConnectionHeader = "X-Radiko-Connection" RadikoLocationHeader = "X-Radiko-Location" RadikoPartialKeyHeader = "X-Radiko-Partialkey" )
Variables ¶
var ( // Base64FullKey holds the /assets/flutter_assets/assets/key/android.jpg in the v8 APK //go:embed assets/base64-full.key Base64FullKey embed.FS // CoordinatesJSON is a JSON contains the base GPS locations //go:embed assets/coordinates.json CoordinatesJSON embed.FS // RegionsJSON is a JSON contains the region mapping //go:embed assets/regions.json RegionsJSON embed.FS // VersionsJSON is a JSON contains the valid SDK versions //go:embed assets/versions.json VersionsJSON embed.FS )
var ( CurrentTime time.Time Location *time.Location )
Functions ¶
func GetRadikronPath ¶ added in v0.7.2
GetRadikronPath resolves a provided path (or defaults to the user's Downloads/radiko directory). If a relative path is provided, it's resolved relative to the current working directory. If an absolute path is provided, it's used as-is. If no path is provided, it defaults to the user's Downloads/radiko directory, with a fallback to the current working directory/radiko if the home directory cannot be determined.
func InitSemaphores ¶ added in v0.6.3
func InitSemaphores(asset *Asset)
InitSemaphores initializes or updates the semaphores based on the asset's concurrency settings. This should be called when configuration is applied to ensure semaphores match the config.
func NewOutputConfig ¶ added in v0.7.2
func NewOutputConfig(fileBaseName, fileFormat, downloadDir, folder string) (*radigo.OutputConfig, error)
NewOutputConfig prepares the outputdir
Types ¶
type Asset ¶
type Asset struct {
AvailableStations []string
AreaDevices Devices
Base64Key string
Coordinates Coordinates
DefaultClient *radiko.Client
// MinimumOutputSize in bytes for the downloaded audio
MinimumOutputSize int64
NextFetchTime *time.Time
OutputFormat string
DownloadDir string // directory name for downloads (default: "radiko")
Regions Regions
Rules Rules
Schedules Schedules
Stations Stations
Versions Versions
// MaxDownloadingConcurrency limits concurrent download operations
MaxDownloadingConcurrency int
// MaxEncodingConcurrency limits concurrent encoding operations (MP3 conversion)
MaxEncodingConcurrency int
}
func (*Asset) AddExtraStations ¶
AddExtraStations appends stations to AvailableStations
func (*Asset) GenerateGPSForAreaID ¶
GenerateGPS returns the RadikoLocationHeader GPS string e.g., "35.689492,139.691701,gps"
func (*Asset) GetAreaIDByStationID ¶
GetAreaIDByStationID returns the first AreaID for the station
func (*Asset) GetPartialKey ¶
GetPartialKey returns the partial key for auth2 API
func (*Asset) GetStationIDsByAreaID ¶
GetStationIDsByAreaID returns a slice of StationIDs
func (*Asset) LoadAvailableStations ¶
LoadAvailableStations loads up the avaialable stations
func (*Asset) RemoveIgnoreStations ¶
RemoveIgnoreStations remove stations from AvailableStations
func (*Asset) UnmarshalJSON ¶
UnmarshalJSON loads up Coordinates with Regions
type ContextKey ¶
type ContextKey string
type Coordinate ¶
type Coordinates ¶
type Coordinates map[string]*Coordinate
type Device ¶
type EventEmitter ¶ added in v0.7.0
type EventEmitter interface {
// EmitDownloadStarted emits when a download starts
EmitDownloadStarted(stationID, title, startTime, uri string)
// EmitDownloadCompleted emits when a download completes successfully (file written to disk)
EmitDownloadCompleted(stationID, title, startTime, filePath string)
// EmitFileSaved emits when a file is fully saved with metadata tags
EmitFileSaved(stationID, title, filePath string)
// EmitDownloadSkipped emits when a download is skipped (duplicate, already exists, etc.)
EmitDownloadSkipped(reason string, stationID, title, startTime string)
// EmitEncodingStarted emits when encoding to MP3 starts
EmitEncodingStarted(filePath string)
// EmitEncodingCompleted emits when encoding to MP3 completes successfully
EmitEncodingCompleted(filePath string)
// EmitLogMessage emits a general log message (for backward compatibility)
EmitLogMessage(level string, message string)
}
EventEmitter defines the interface for emitting structured events. Implementations can provide structured events to external systems (e.g., GUI).
func GetEventEmitter ¶ added in v0.7.0
func GetEventEmitter(ctx context.Context) EventEmitter
GetEventEmitter retrieves the EventEmitter from context, if available. Returns nil if no emitter is set in context (CLI mode).
type Prog ¶
type Prog struct {
ID string
StationID string
Ft string
To string
Title string
Desc string
Info string
Pfm string
Tags []string
Genre ProgGenre
M3U8 string
RuleName string // name of the rule that matched this program
RuleFolder string // folder from the rule that matched this program
IsManualInjection bool // true if this program was manually injected
}
Prog contains the solicited program metadata
type Progs ¶
type Progs []*Prog
Progs is a slice of Prog.
func FetchWeeklyPrograms ¶
FetchWeeklyPrograms returns the weekly programs.
func (*Progs) UnmarshalXML ¶
type Rule ¶
type Rule struct {
Name string `mapstructure:"name"` // required
Title string `mapstructure:"title"` // required if pfm and keyword are unset
DoW []string `mapstructure:"dow"` // optional
Keyword string `mapstructure:"keyword"` // optional
Pfm string `mapstructure:"pfm"` // optional
StationID string `mapstructure:"station-id"` // optional
Window string `mapstructure:"window"` // optional
Folder string `mapstructure:"folder"` // optional
}
func (*Rule) HasKeyword ¶
func (*Rule) HasStationID ¶
func (*Rule) Match ¶
Match returns true if the rule matches the program 1. check the Window filter 2. check the DoW filter 3. check the StationID 4. match the criteria
func (*Rule) MatchKeyword ¶
func (*Rule) MatchSilent ¶ added in v0.7.0
MatchSilent returns true if the rule matches the program without logging
func (*Rule) MatchStationID ¶
func (*Rule) MatchTitle ¶
func (*Rule) MatchWindow ¶
type Rules ¶
type Rules []*Rule
func (Rules) FindMatch ¶ added in v0.6.0
FindMatch returns the first matching rule for the given station and program
func (Rules) FindMatchSilent ¶ added in v0.7.0
FindMatchSilent returns the first matching rule without logging This is useful when checking for matches on programs that may be skipped
func (Rules) HasRuleForStationID ¶
func (Rules) HasRuleWithCriteria ¶ added in v0.7.2
HasRuleWithCriteria returns true if at least one rule has optional criteria (Title, Pfm, or Keyword)
func (Rules) HasRuleWithoutStationID ¶
type XMLProg ¶
type XMLProg struct {
ID string `xml:"id,attr"`
Ft string `xml:"ft,attr"`
To string `xml:"to,attr"`
Title string `xml:"title"`
Desc string `xml:"desc"`
Info string `xml:"info"`
Pfm string `xml:"pfm"`
Tag struct {
Item []XMLProgItem `xml:"item"`
} `xml:"tag"`
Genre struct {
Personality XMLProgItem `xml:"personality"`
Program XMLProgItem `xml:"program"`
} `xml:"genre"`
}
XMLProg contains the raw program metadata
type XMLProgItem ¶
type XMLRegion ¶
type XMLRegion struct {
Region []XMLRegionStations `xml:"stations"`
}
func FetchXMLRegion ¶
type XMLRegionStation ¶
type XMLRegionStations ¶
type XMLRegionStations struct {
Stations []XMLRegionStation `xml:"station"`
RegionID string `xml:"region_id,attr"`
RegionName string `xml:"region_name,attr"`
}
type XMLWeekly ¶
type XMLWeekly struct {
XMLName xml.Name `xml:"radiko"`
XMLStations struct {
XMLName xml.Name `xml:"stations"`
Station []XMLWeeklyStation `xml:"station"`
} `xml:"stations"`
}
