From 3c554922c835900e587d29472731cea658c2ddf2 Mon Sep 17 00:00:00 2001 From: Totto16 <32566573+Totto16@users.noreply.github.com> Date: Fri, 21 Oct 2022 18:35:11 +0200 Subject: [PATCH] Add SunXdcc search provider (#1) --- main.go | 1 + search.go | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 112 insertions(+), 8 deletions(-) diff --git a/main.go b/main.go index af4c2c5..5544a5b 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,7 @@ var registry *XdccProviderRegistry = nil func init() { registry = NewProviderRegistry() registry.AddProvider(&XdccEuProvider{}) + registry.AddProvider(&SunXdccProvider{}) } var defaultColWidths []int = []int{100, 10, -1} diff --git a/search.go b/search.go index 806f67a..b2ab85a 100644 --- a/search.go +++ b/search.go @@ -1,7 +1,9 @@ package main import ( + "encoding/json" "errors" + "fmt" "log" "net/http" "strconv" @@ -65,10 +67,6 @@ func (registry *XdccProviderRegistry) Search(keywords []string) ([]XdccFileInfo, return allResults, nil } -type XdccEuProvider struct{} - -const XdccEuURL = "https://www.xdcc.eu/search.php" - func parseFileSize(sizeStr string) (int64, error) { if len(sizeStr) == 0 { return -1, errors.New("empty string") @@ -92,11 +90,15 @@ func parseFileSize(sizeStr string) (int64, error) { return -1, errors.New("unable to parse: " + sizeStr) } +type XdccEuProvider struct{} + +const XdccEuURL = "https://www.xdcc.eu/search.php" + const xdccEuNumberOfEntries = 7 func (p *XdccEuProvider) parseFields(fields []string) (*XdccFileInfo, error) { if len(fields) != xdccEuNumberOfEntries { - return nil, errors.New("unespected number of search entry fields") + return nil, errors.New("unexpected number of search entry fields") } fInfo := &XdccFileInfo{} @@ -132,9 +134,8 @@ func (p *XdccEuProvider) Search(keywords []string) ([]XdccFileInfo, error) { } defer res.Body.Close() - if res.StatusCode != 200 { - log.Fatalf("status code error: %d %s", res.StatusCode, res.Status) - return nil, err + if res.StatusCode != http.StatusOK { + return nil, errors.New(fmt.Sprintf("status code error: %d %s", res.StatusCode, res.Status)) } // Load the HTML document @@ -167,3 +168,105 @@ func (p *XdccEuProvider) Search(keywords []string) ([]XdccFileInfo, error) { }) return fileInfos, nil } + +type SunXdccProvider struct{} + +const SunXdccURL = "http://sunxdcc.com/deliver.php" + +const SunXdccNumberOfEntries = 8 + +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] + + slot, err := strconv.Atoi(entry.Packnum[index][1:]) + + if err != nil { + return nil, err + } + + sizeString := strings.TrimLeft(strings.TrimRight(entry.Fsize[index], "]"), "[") + + fInfo.Size, _ = parseFileSize(sizeString) // ignoring error + + fInfo.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 +} + +type SunXdccEntry 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), "+") + // for API definition use https://sunxdcc.com/#api + res, err := http.Get(SunXdccURL + "?sterm=" + searchkey) + + if err != nil { + log.Fatal(err) + return nil, err + } + + defer res.Body.Close() + if res.StatusCode != http.StatusOK { + return nil, errors.New(fmt.Sprintf("status code error: %d %s", res.StatusCode, res.Status)) + } + + // Load the JSON Response document + + var entry SunXdccEntry + decoder := json.NewDecoder(res.Body) + if err := decoder.Decode(&entry); err != nil { + return nil, err + } + + var 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)} + + var length = sizes[0] + for _, l := range sizes { + if length != l { + log.Fatalf("Parse Error, not all fields have the same size") + return nil, errors.New("Parse Error, not all fields have the same size") + } + } + + fileInfos := make([]XdccFileInfo, 0) + + for i := 0; i < len(entry.Botrec); i++ { + + info, err := p.parseFields(entry, i) + if err == nil { + fileInfos = append(fileInfos, *info) + } + } + + return fileInfos, nil +}