xdcc-cli/search/search.go

99 lines
1.9 KiB
Go

package search
import (
"errors"
"strconv"
"sync"
"xdcc-cli/xdcc"
)
type XdccFileInfo struct {
URL xdcc.IRCFile
Name string
Size int64
Slot int
}
type XdccSearchProvider interface {
Search(keywords []string) ([]XdccFileInfo, error)
}
type ProviderAggregator struct {
providerList []XdccSearchProvider
}
const MaxProviders = 100
func NewProviderAggregator(providers ...XdccSearchProvider) *ProviderAggregator {
return &ProviderAggregator{
providerList: providers,
}
}
func (registry *ProviderAggregator) AddProvider(provider XdccSearchProvider) {
registry.providerList = append(registry.providerList, provider)
}
const MaxResults = 1024
func (registry *ProviderAggregator) Search(keywords []string) ([]XdccFileInfo, error) {
allResults := make(map[xdcc.IRCFile]XdccFileInfo)
mtx := sync.Mutex{}
wg := sync.WaitGroup{}
wg.Add(len(registry.providerList))
for _, p := range registry.providerList {
go func(p XdccSearchProvider) {
resList, err := p.Search(keywords)
if err != nil {
return
}
mtx.Lock()
for _, res := range resList {
allResults[res.URL] = res
}
mtx.Unlock()
wg.Done()
}(p)
}
wg.Wait()
results := make([]XdccFileInfo, 0, MaxResults)
for _, res := range allResults {
results = append(results, res)
}
return results, nil
}
const (
KiloByte = 1024
MegaByte = KiloByte * 1024
GigaByte = MegaByte * 1024
)
func parseFileSize(sizeStr string) (int64, error) {
if len(sizeStr) == 0 {
return -1, errors.New("empty string")
}
lastChar := sizeStr[len(sizeStr)-1]
sizePart := sizeStr[:len(sizeStr)-1]
size, err := strconv.ParseFloat(sizePart, 32)
if err != nil {
return -1, err
}
switch lastChar {
case 'G':
return int64(size * GigaByte), nil
case 'M':
return int64(size * MegaByte), nil
case 'K':
return int64(size * KiloByte), nil
}
return -1, errors.New("unable to parse: " + sizeStr)
}