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