diff --git a/main.go b/main.go index 5544a5b..3a0086a 100644 --- a/main.go +++ b/main.go @@ -65,12 +65,15 @@ func searchCommand(args []string) { res, _ := registry.Search(args) for _, fileInfo := range res { - printer.AddRow(Row{fileInfo.Name, formatSize(fileInfo.Size), fileInfo.Url}) + printer.AddRow(Row{fileInfo.Name, formatSize(fileInfo.Size), fileInfo.URL.String()}) } + sortColumn := 2 if *sortByFilename { - printer.SortByColumn(0) + sortColumn = 0 } + printer.SortByColumn(sortColumn) + printer.Print() } @@ -104,7 +107,6 @@ func suggestUnknownAuthoritySwitch(err error) { func doTransfer(transfer *XdccTransfer) { err := transfer.Start() - if err != nil { fmt.Println(err) suggestUnknownAuthoritySwitch(err) @@ -180,7 +182,7 @@ func getCommand(args []string) { wg := sync.WaitGroup{} for _, urlStr := range urlList { if strings.HasPrefix(urlStr, "irc://") { - url, err := parseIRCFileURl(urlStr) + url, err := parseURL(urlStr) if err != nil { fmt.Println(err.Error()) diff --git a/search.go b/search.go index 875fe79..4333901 100644 --- a/search.go +++ b/search.go @@ -14,13 +14,10 @@ import ( ) type XdccFileInfo struct { - Network string - Channel string - BotName string - Name string - Url string - Size int64 - Slot int + URL IRCFile + Name string + Size int64 + Slot int } type XdccSearchProvider interface { @@ -46,25 +43,35 @@ func (registry *XdccProviderRegistry) AddProvider(provider XdccSearchProvider) { const MaxResults = 1024 func (registry *XdccProviderRegistry) Search(keywords []string) ([]XdccFileInfo, error) { - allResults := make([]XdccFileInfo, 0, MaxResults) + allResults := make(map[IRCFile]XdccFileInfo) + + mtx := sync.Mutex{} wg := sync.WaitGroup{} wg.Add(len(registry.providerList)) for _, p := range registry.providerList { go func(p XdccSearchProvider) { - res, err := p.Search(keywords) - + resList, err := p.Search(keywords) if err != nil { return } - allResults = append(allResults, res...) + mtx.Lock() + for _, res := range resList { + allResults[res.URL] = res + } + mtx.Unlock() wg.Done() }(p) } wg.Wait() - return allResults, nil + + results := make([]XdccFileInfo, 0, MaxResults) + for _, res := range allResults { + results = append(results, res) + } + return results, nil } func parseFileSize(sizeStr string) (int64, error) { @@ -102,11 +109,10 @@ func (p *XdccEuProvider) parseFields(fields []string) (*XdccFileInfo, error) { } fInfo := &XdccFileInfo{} - fInfo.Network = fields[0] - fInfo.Channel = fields[1] - fInfo.BotName = fields[2] + fInfo.URL.Network = fields[0] + fInfo.URL.Channel = fields[1] + fInfo.URL.UserName = fields[2] slot, err := strconv.Atoi(fields[3][1:]) - if err != nil { return nil, err } @@ -149,12 +155,12 @@ func (p *XdccEuProvider) Search(keywords []string) ([]XdccFileInfo, error) { doc.Find("tr").Each(func(_ int, s *goquery.Selection) { fields := make([]string, 0) - var url string + var urlStr string s.Children().Each(func(i int, si *goquery.Selection) { if i == 1 { value, exists := si.Find("a").First().Attr("href") if exists { - url = value + urlStr = value } } fields = append(fields, strings.TrimSpace(si.Text())) @@ -162,8 +168,11 @@ func (p *XdccEuProvider) Search(keywords []string) ([]XdccFileInfo, error) { info, err := p.parseFields(fields) if err == nil { - info.Url = url + "/" + info.BotName + "/" + strconv.Itoa(info.Slot) - fileInfos = append(fileInfos, *info) + url, err := parseURL(urlStr + "/" + info.URL.UserName + "/" + strconv.Itoa(info.Slot)) + if err == nil { + info.URL = *url + fileInfos = append(fileInfos, *info) + } } }) return fileInfos, nil @@ -177,11 +186,10 @@ const ( type SunXdccProvider struct{} func (p *SunXdccProvider) parseFields(entry *SunXdccEntry, index int) (*XdccFileInfo, error) { - - fInfo := &XdccFileInfo{} - fInfo.Network = entry.Network[index] - fInfo.BotName = entry.Bot[index] - fInfo.Channel = entry.Channel[index] + info := &XdccFileInfo{} + info.URL.Network = entry.Network[index] + info.URL.UserName = entry.Bot[index] + info.URL.Channel = entry.Channel[index] slot, err := strconv.Atoi(entry.Packnum[index][1:]) @@ -191,19 +199,14 @@ func (p *SunXdccProvider) parseFields(entry *SunXdccEntry, index int) (*XdccFile sizeString := strings.TrimLeft(strings.TrimRight(entry.Fsize[index], "]"), "[") - fInfo.Size, _ = parseFileSize(sizeString) // ignoring error - - fInfo.Name = entry.Fname[index] - + info.Size, _ = parseFileSize(sizeString) // ignoring error + info.Name = entry.Fname[index] if err != nil { return nil, err } - fInfo.Slot = slot - - fInfo.Url = "irc://" + fInfo.Network + "/" + strings.TrimLeft(fInfo.Channel, "#") + "/" + fInfo.BotName + "/" + strconv.Itoa(fInfo.Slot) - - return fInfo, nil + info.Slot = slot + return info, nil } type SunXdccEntry struct { diff --git a/url.go b/url.go index 877cfe8..e3d448e 100644 --- a/url.go +++ b/url.go @@ -7,7 +7,7 @@ import ( "strings" ) -type IRCFileURL struct { +type IRCFile struct { Network string Channel string UserName string @@ -29,8 +29,8 @@ func parseSlot(slotStr string) (int, error) { return strconv.Atoi(slotStr) } -// url has the following format: irc://network/channel/bot/#slot -func parseIRCFileURl(url string) (*IRCFileURL, error) { +// url has the following format: irc://network/channel/bot/slot +func parseURL(url string) (*IRCFile, error) { if !strings.HasPrefix(url, "irc://") { return nil, errors.New("not an IRC url") } @@ -45,7 +45,7 @@ func parseIRCFileURl(url string) (*IRCFileURL, error) { return nil, err } - fileUrl := &IRCFileURL{ + fileUrl := &IRCFile{ Network: fields[0], Channel: fields[1], UserName: fields[2], @@ -58,10 +58,10 @@ func parseIRCFileURl(url string) (*IRCFileURL, error) { return fileUrl, nil } -func (url *IRCFileURL) GetBot() IRCBot { +func (url *IRCFile) GetBot() IRCBot { return IRCBot{Network: url.Network, Channel: url.Channel, Name: url.UserName} } -func (url *IRCFileURL) String() string { - return fmt.Sprintf("irc://%s/%s/%s/#%d", url.Network, url.Channel, url.UserName, url.Slot) +func (url *IRCFile) String() string { + return fmt.Sprintf("irc://%s/%s/%s/%d", url.Network, url.Channel, url.UserName, url.Slot) } diff --git a/xdcc.go b/xdcc.go index ad18b3b..359215c 100644 --- a/xdcc.go +++ b/xdcc.go @@ -129,14 +129,14 @@ const maxConnAttempts = 5 type XdccTransfer struct { filePath string - url IRCFileURL + url IRCFile conn *irc.Conn connAttempts int started bool events chan TransferEvent } -func NewXdccTransfer(url IRCFileURL, filePath string, enableSSL bool, skipCertificateCheck bool) *XdccTransfer { +func NewXdccTransfer(url IRCFile, filePath string, enableSSL bool, skipCertificateCheck bool) *XdccTransfer { rand.Seed(time.Now().UTC().UnixNano()) nick := IRCClientUserName + strconv.Itoa(int(rand.Uint32()))