Documentation
¶
Overview ¶
Package nzb parses NZB documents: the XML index of a Usenet post that lists every file, its newsgroups and the message IDs of its segments (articles). Besides the raw structure it derives file names from subjects, classifies files (video, archive volumes, par2, extras), flags obfuscated names and groups archive volumes into ordered sets, which is what the stream engine needs to find the playable file of a release.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrInvalid = errors.New("nzb: invalid document")
ErrInvalid is returned for documents that are not usable NZBs.
Functions ¶
func IsObfuscated ¶
IsObfuscated reports whether a name carries no information about the content: no extension, a hash/UUID-like base, a long random token, or the "abc.xyz" placeholder some posters use.
func IsPar2Volume ¶
IsPar2Volume reports whether name is a PAR2 recovery volume ("x.vol03+04.par2") rather than an index file ("x.par2").
func IsVideoExt ¶
IsVideoExt reports whether ext (without dot, any case) is a video container.
func NameFromSubject ¶
NameFromSubject extracts the file name from a Usenet subject line, e.g.
`"Movie.2024.part01.rar" yEnc (1/50)` -> Movie.2024.part01.rar `[01/42] - "Movie.2024.mkv" yEnc (1/1000)` -> Movie.2024.mkv `[PRiVATE]-[WtFnZb]-[Movie.2024.mkv]-[1/5] - "" yEnc` -> Movie.2024.mkv `Movie.2024.r00 (1/50)` -> Movie.2024.r00
Types ¶
type File ¶
type File struct {
Index int // position in NZB.Files
Poster string
Date time.Time
Subject string
Groups []string
// Segments sorted by Number, de-duplicated (the first occurrence of a
// number wins).
Segments []Segment
// Name is the file name derived from the subject (may be obfuscated).
Name string
// Obfuscated reports that Name looks random (hashes, missing extension),
// so it says nothing about the content.
Obfuscated bool
// Info classifies Name.
Info FileInfo
// SubjectIndex / SubjectCount are the "[03/50]" file counter in the
// subject, 0 when absent. Useful to order obfuscated volumes.
SubjectIndex int
SubjectCount int
// ExpectedSegments is the "(1/N)" segment count in the subject, or 0.
ExpectedSegments int
// Duplicates counts dropped repeated segment numbers.
Duplicates int
}
File is one posted file.
func Par2Index ¶
Par2Index returns the PAR2 index file among files: the smallest file classified as PAR2 that is not a recovery volume (preferring one that is not a sample's), or nil. The index holds only metadata packets (file names, sizes, hashes), typically a few KB.
func (*File) Bytes ¶
Bytes is the sum of the listed segment sizes. It is the encoded article size, a few percent larger than the decoded file; use it for comparisons.
func (*File) Missing ¶
Missing returns the segment numbers in 1..SegmentCount() that the NZB does not list.
func (*File) SegmentCount ¶
SegmentCount is the number of part slots the file has: the highest segment number seen or announced by the subject.
type FileInfo ¶
type FileInfo struct {
Kind Kind
// Ext is the lower-cased extension of the content: "mkv" for
// "movie.mkv" and for "movie.mkv.001"; "rar" / "7z" for archives.
Ext string
// Volume is the 0-based position of an archive volume in its set
// (.rar=0, .r00=1, .part01.rar=0, .7z.001=0, .001=0). -1 otherwise.
Volume int
// SetName is the lower-cased name shared by every volume of a set, so
// volumes group by (Kind, SetName). For other files it is the
// lower-cased name without extension.
SetName string
// NewStyle is true for .partNN.rar naming, false for .rar/.rNN.
NewStyle bool
// Sample and Extra flag short clips that are not the feature.
Sample bool
Extra bool
}
FileInfo is what a file name says about a posted file.
type Kind ¶
type Kind int
Kind classifies a posted file by its name.
const ( KindUnknown Kind = iota KindVideo // a playable container (.mkv, .mp4, ...) KindRAR // a RAR volume (.rar, .r00, .partNN.rar) KindSevenZip // a 7z volume (.7z, .7z.001) KindSplit // a plain split volume (.001, .mkv.001) KindPar2 KindNFO KindSFV KindSubtitle KindImage KindOther // known but irrelevant (.txt, .nzb, .srr, .iso, ...) )
type NZB ¶
type NZB struct {
// Meta holds <head><meta type="..."> values by lower-cased type.
Meta map[string][]string
// Files in document order. Files without any valid segment are dropped.
Files []*File
}
NZB is a parsed document.
func ParseReader ¶
ParseReader parses an NZB document from r.
func (*NZB) ArchiveSets ¶
ArchiveSets groups archive volumes by set and orders them. Sets are returned largest first.
type Segment ¶
type Segment struct {
Number int // 1-based part number
Bytes int64 // article size as listed in the NZB (encoded, approximate)
MessageID string // without angle brackets
}
Segment is one article of a file.
type Set ¶
type Set struct {
Kind Kind
// Name is the lower-cased set name shared by the volumes
// ("movie.2024" for movie.2024.part01.rar, "movie.mkv" for movie.mkv.001).
Name string
// NewStyle is true for .partNN.rar sets.
NewStyle bool
// Volumes in order; gaps are listed in Missing. The files' Info is left
// untouched (a part00/.000 set keeps numbering from -1), so grouping the
// same files again gives the same result and concurrent callers do not
// write shared files.
Volumes []*File
// Missing lists absent 0-based volume numbers below the highest present.
Missing []int
// Duplicates are reposted volumes that lost to a larger copy.
Duplicates []*File
}
Set is the ordered volumes of one archive (RAR, 7z or plain split).