VNZB
A high-performance NZB (Newzbin) parsing and manipulation library written in V. VNZB provides zero-dependency, memory-safe operations for working with NZB files, extracting metadata, and managing Usenet article information.
Features
-
🚀 High Performance
: Zero-allocation parsing where possible, optimized for large NZB files -
🔒 Memory Safe
: Leverages V's memory safety and type system -
📦 Zero Dependencies
: Pure V implementation with no external dependencies -
📄 NZB Support
: Parse and create NZB 1.0 and 1.1 compliant files -
🔧 Manipulation
: Filter, merge, and analyze NZB content -
📊 Completion Analysis
: Analyze file completeness and missing segments -
✅ Spec Compliant
: Follows NZB XML specification
Installation
Add VNZB to your V project:
v install https://github.com/watzon/vnzb
Or add to your
v.mod
dependencies: ['vnzb']
Quick Start
Parsing NZB Files
import vnzb
// Parse an NZB file
nzb_data := vnzb.parse_file('example.nzb') or {
eprintln('Failed to parse NZB: ${err}')
return
}
println('Files: ${nzb_data.files.len}')
println('Total size: ${nzb_data.total_bytes}')
// Access metadata
if nzb_data.has_metadata() {
println('Title: ${nzb_data.head.meta['title']}')
}
Creating NZB Files
import vnzb
// Create a new NZB builder
mut builder := vnzb.new_builder()
// Add metadata
builder.add_meta('title', 'My Download')
builder.add_meta('category', 'Movies')
// Create a file entry
mut file := vnzb.NZBFile{
poster: '[email protected]'
subject: 'Movie.2024.1080p.BluRay.x264.mkv (1/3)'
groups: ['alt.binaries.movies']
segments: []
}
// Add segments
file.add_segment(1, 15000000, '[email protected]')
file.add_segment(2, 15000000, '[email protected]')
file.add_segment(3, 8500000, '[email protected]')
// Add file to NZB
builder.add_file(file)
// Build and save
nzb := builder.build()!
nzb.save('output.nzb')!
Filtering Files
import vnzb
nzb := vnzb.parse_file('download.nzb')!
// Filter video files only
video_options := vnzb.video_filter()
video_nzb := vnzb.filter(&nzb, video_options)
// Filter by size
size_options := vnzb.no_small_files_filter(10) // 10MB minimum
large_files := vnzb.filter(&nzb, size_options)
// Custom filter
options := vnzb.FilterOptions{
min_size: 5 * 1024 * 1024 // 5MB
max_size: 100 * 1024 * 1024 // 100MB
exclude_samples: true
exclude_nfo: true
include_patterns: [r'\.mkv$', r'\.mp4$']
}
filtered := vnzb.filter(&nzb, options)
Merging NZB Files
import vnzb
// Parse multiple NZB files
nzb1 := vnzb.parse_file('part1.nzb')!
nzb2 := vnzb.parse_file('part2.nzb')!
// Simple merge
merged := vnzb.merge_two(&nzb1, &nzb2)
// Merge with options
options := vnzb.MergeOptions{
deduplicate: true
merge_metadata: true
metadata_strategy: .merge
sort_by: .name
}
merged := vnzb.merge([&nzb1, &nzb2], options)
// Save merged result
merged.save('complete.nzb')!
Completion Analysis
import vnzb
nzb := vnzb.parse_file('download.nzb')!
// Get completion report
report := vnzb.analyze_completion(&nzb)
println('Completion: ${report.completion_percentage:.1f}%')
// Check if complete enough (e.g., 90% threshold)
if vnzb.is_complete_enough(&nzb, 90.0) {
println('NZB is sufficiently complete')
}
// Get complete/incomplete files
complete_files := vnzb.get_complete_files(&nzb)
incomplete_files := vnzb.get_incomplete_files(&nzb)
for file in incomplete_files {
println('Incomplete: ${file.filename}')
}
NZB Format
VNZB supports the NZB 1.1 specification:
<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE nzb PUBLIC "-//newzBin//DTD NZB 1.1//EN" "http://www.newzbin.com/DTD/nzb/nzb-1.1.dtd">
<nzb xmlns="http://www.newzbin.com/DTD/2003/nzb">
<head>
<meta type="title">Your File!</meta>
<meta type="password">secret</meta>
</head>
<file poster="Joe Bloggs <[email protected]>" date="1071674882" subject="Here's your file! abc-mr2a.r01 (1/2)">
<groups>
<group>alt.binaries.newzbin</group>
</groups>
<segments>
<segment bytes="102394" number="1">[email protected]</segment>
<segment bytes="4501" number="2">[email protected]</segment>
</segments>
</file>
</nzb>
Command Line Tool
VNZB includes a command-line tool for common operations:
# Show NZB information
vnzb-cli info file.nzb
# Validate NZB structure
vnzb-cli validate file.nzb
# Filter files
vnzb-cli filter --video file.nzb # Video files only
vnzb-cli filter --min-size 10 --max-size 100 file.nzb # Size range (MB)
vnzb-cli filter --video -o videos.nzb file.nzb # Save to file
# Merge NZB files
vnzb-cli merge file1.nzb file2.nzb -o merged.nzb
vnzb-cli merge *.nzb --sort size -o sorted.nzb
# Analyze completion
vnzb-cli completion file.nzb
API Reference
Types
-
NZB: Main NZB structure containing files and metadata -
NZBFile: Individual file with segments -
Segment: File segment with message ID -
NZBBuilder: Builder for creating NZB files -
FilterOptions: Options for filtering files -
MergeOptions: Options for merging NZBs -
CompletionReport: Detailed completion analysis
Core Functions
-
parse(data []u8) !NZB: Parse NZB from bytes -
parse_file(path string) !NZB: Parse NZB from file -
new_builder() NZBBuilder: Create new NZB builder -
(nzb &NZB) validate() !: Validate NZB structure -
(nzb &NZB) to_xml() string: Convert to XML -
(nzb &NZB) save(path string) !: Save to file
Manipulation Functions
-
filter(nzb &NZB, options FilterOptions) NZB: Filter files -
merge(nzbs []&NZB, options MergeOptions) NZB: Merge multiple NZBs -
analyze_completion(nzb &NZB) CompletionReport: Analyze completion -
is_complete_enough(nzb &NZB, threshold f64) bool: Check completion threshold
Development Status
This library is under active development. Currently implemented:
- ✅ Core data structures
- ✅ NZB parsing with XML entity handling
- ✅ NZB building and XML generation
- ✅ File filtering (size, patterns, file types)
- ✅ NZB merging with deduplication
- ✅ Completion analysis
- ✅ Command-line tool
- ❌ Splitting large NZBs
- ❌ Parallel processing optimizations
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.