115 lines
2.5 KiB
Go
115 lines
2.5 KiB
Go
package search
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
sunXdccURL = "http://sunxdcc.com/deliver.php"
|
|
sunXdccNumberOfEntries = 8
|
|
)
|
|
|
|
type SunXdccProvider struct{}
|
|
|
|
func (p *SunXdccProvider) parseResponseEntry(entry *SunXdccResponse, index int) (*XdccFileInfo, error) {
|
|
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:])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
sizeString := strings.TrimLeft(strings.TrimRight(entry.Fsize[index], "]"), "[")
|
|
|
|
info.Size, _ = parseFileSize(sizeString) // ignoring error
|
|
info.Name = entry.Fname[index]
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
info.Slot = slot
|
|
return info, nil
|
|
}
|
|
|
|
type SunXdccResponse struct {
|
|
Botrec []string
|
|
Network []string
|
|
Bot []string
|
|
Channel []string
|
|
Packnum []string
|
|
Gets []string
|
|
Fsize []string
|
|
Fname []string
|
|
}
|
|
|
|
func (p *SunXdccProvider) Search(keywords []string) ([]XdccFileInfo, error) {
|
|
keywordString := strings.Join(keywords, " ")
|
|
searchkey := strings.Join(strings.Fields(keywordString), "+")
|
|
// see https://sunxdcc.com/#api for API definition
|
|
httpResp, err := http.Get(sunXdccURL + "?sterm=" + searchkey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
defer httpResp.Body.Close()
|
|
if httpResp.StatusCode != http.StatusOK {
|
|
return nil, fmt.Errorf("status code error: %d %s", httpResp.StatusCode, httpResp.Status)
|
|
}
|
|
|
|
resp, err := p.parseResponse(httpResp)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !p.validateResult(resp) {
|
|
return nil, fmt.Errorf("parse Error, not all fields have the same size")
|
|
}
|
|
return p.parseResults(resp)
|
|
}
|
|
|
|
func (p *SunXdccProvider) parseResults(resp *SunXdccResponse) ([]XdccFileInfo, error) {
|
|
fileInfos := make([]XdccFileInfo, 0)
|
|
for i := 0; i < len(resp.Botrec); i++ {
|
|
info, err := p.parseResponseEntry(resp, i)
|
|
if err == nil {
|
|
fileInfos = append(fileInfos, *info)
|
|
}
|
|
}
|
|
return fileInfos, nil
|
|
}
|
|
|
|
func (*SunXdccProvider) validateResult(entry *SunXdccResponse) bool {
|
|
sizes := [8]int{
|
|
len(entry.Botrec),
|
|
len(entry.Network),
|
|
len(entry.Bot),
|
|
len(entry.Channel),
|
|
len(entry.Packnum),
|
|
len(entry.Gets),
|
|
len(entry.Fsize),
|
|
len(entry.Fname),
|
|
}
|
|
|
|
length := sizes[0]
|
|
for _, l := range sizes {
|
|
if length != l {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (*SunXdccProvider) parseResponse(res *http.Response) (*SunXdccResponse, error) {
|
|
entry := &SunXdccResponse{}
|
|
decoder := json.NewDecoder(res.Body)
|
|
err := decoder.Decode(entry)
|
|
return entry, err
|
|
}
|