99 lines
1.9 KiB
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)
|
|
}
|