// Copyright (C) 2021 nytpu // SPDX-License-Identifier: AGPL-3.0-or-later // For more license details, see LICENSE or . package fetch import ( "bytes" "crypto/sha256" "fmt" "io" "time" "github.com/mmcdole/gofeed" "github.com/prologic/go-gopher" "golang.nytpu.com/comitium/core" ) // fetchGopher will make a request for a gopher resource func fetchGopher(remote string) (*gopher.Response, error) { resp, err := gopher.Get(remote) if err != nil { return nil, err } return resp, nil } // gopherFeed will fetch and insert a new core.Feed into a core.FullData given a // gopher url (or update if it's preexisting) func gopherFeed(data *core.FullData, remote string, title string) error { resp, err := fetchGopher(remote) if err != nil { return err } defer resp.Body.Close() if len(resp.Dir.Items) != 0 { // TODO return fmt.Errorf("Gemini-style feeds served over gopher are currently unsupported.") } reader := io.LimitReader(resp.Body, 1073741824) // 1 GiB gofeed, err := gofeed.NewParser().Parse(reader) if err != nil { return err } feed, err := core.GofeedConvert(gofeed, title) if err != nil { return err } data.InsertFeed(feed, remote) return nil } // gopherPage will fetch and insert a new core.Page into a core.FullData given a // gopher url (or update if it's preexisting) func gopherPage(data *core.FullData, remote string, title string) error { resp, err := fetchGopher(remote) if err != nil { return err } defer resp.Body.Close() var reader io.Reader if len(resp.Dir.Items) > 0 { text, err := resp.Dir.ToText() if err != nil { return err } reader = io.LimitReader(bytes.NewReader(text), 1073741824) // 1 GiB } else { reader = io.LimitReader(resp.Body, 1073741824) // 1 GiB } var page core.Page page.Title = title page.Link = remote h := sha256.New() if _, err := io.Copy(h, reader); err != nil { return err } newHash := fmt.Sprintf("%x", h.Sum(nil)) page.Hash = newHash page.Updated = time.Now() data.InsertPage(&page, remote) return nil }