Clean slate initialization of Goondex - a fast, local-first media indexer. Features: - SQLite database with WAL mode and foreign keys - Full schema for performers, studios, scenes, and tags - Many-to-many relationships via junction tables - CRUD stores for all entities with search capabilities - CLI with performer/studio/scene search commands - Pluggable scraper architecture with registry - TPDB client stub (ready for implementation) - Configuration system via YAML files - Comprehensive .gitignore and documentation Architecture: - cmd/goondex: CLI application with Cobra - cmd/goondexd: Daemon placeholder for v0.2.0 - internal/db: Database layer with stores - internal/model: Clean data models - internal/scraper: Scraper interface and TPDB client - config/: YAML configuration templates Database schema includes indexes on common query fields and uses RFC3339 timestamps for consistency. Built and tested successfully with Go 1.25.4. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
60 lines
1.0 KiB
Go
60 lines
1.0 KiB
Go
package scraper
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
)
|
|
|
|
// Registry manages available scrapers
|
|
type Registry struct {
|
|
mu sync.RWMutex
|
|
scrapers map[string]Scraper
|
|
}
|
|
|
|
// NewRegistry creates a new scraper registry
|
|
func NewRegistry() *Registry {
|
|
return &Registry{
|
|
scrapers: make(map[string]Scraper),
|
|
}
|
|
}
|
|
|
|
// Register adds a scraper to the registry
|
|
func (r *Registry) Register(s Scraper) error {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
|
|
name := s.Name()
|
|
if _, exists := r.scrapers[name]; exists {
|
|
return fmt.Errorf("scraper %q already registered", name)
|
|
}
|
|
|
|
r.scrapers[name] = s
|
|
return nil
|
|
}
|
|
|
|
// Get retrieves a scraper by name
|
|
func (r *Registry) Get(name string) (Scraper, error) {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
|
|
s, ok := r.scrapers[name]
|
|
if !ok {
|
|
return nil, fmt.Errorf("scraper %q not found", name)
|
|
}
|
|
|
|
return s, nil
|
|
}
|
|
|
|
// List returns all registered scraper names
|
|
func (r *Registry) List() []string {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
|
|
names := make([]string, 0, len(r.scrapers))
|
|
for name := range r.scrapers {
|
|
names = append(names, name)
|
|
}
|
|
|
|
return names
|
|
}
|