Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions internal/api/v1/download_clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,6 @@ type dlClientTestInput struct {
}
}

func toDLClientBody(row interface{ GetID() string }) dlClientBody {
// This is handled inline since the generated type doesn't have methods
return dlClientBody{}
}

// RegisterDownloadClientRoutes registers download client management endpoints.
func RegisterDownloadClientRoutes(api huma.API, svc *downloadclient.Service) {
// POST /api/v1/download-clients — create
Expand Down
12 changes: 6 additions & 6 deletions internal/api/v1/torznab.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ func (h *TorznabHandler) handleCaps(w http.ResponseWriter, runner *scraper.Runne

w.Header().Set("Content-Type", "application/xml; charset=utf-8")
w.WriteHeader(http.StatusOK)
w.Write([]byte(xml.Header))
xml.NewEncoder(w).Encode(caps)
_, _ = w.Write([]byte(xml.Header))
_ = xml.NewEncoder(w).Encode(caps)
}

// handleSearch executes a search and returns Torznab XML results.
Expand Down Expand Up @@ -211,8 +211,8 @@ func (h *TorznabHandler) writeResults(w http.ResponseWriter, r *http.Request, id

w.Header().Set("Content-Type", "application/xml; charset=utf-8")
w.WriteHeader(http.StatusOK)
w.Write([]byte(xml.Header))
xml.NewEncoder(w).Encode(feed)
_, _ = w.Write([]byte(xml.Header))
_ = xml.NewEncoder(w).Encode(feed)
}

// xmlError writes a Torznab error response.
Expand Down Expand Up @@ -304,7 +304,7 @@ func (h *TorznabHandler) HandleDownload(w http.ResponseWriter, r *http.Request)
w.Header().Set("Content-Disposition", cd)
}
w.WriteHeader(proxyResp.StatusCode)
io.Copy(w, proxyResp.Body)
_, _ = io.Copy(w, proxyResp.Body)
}

// TestSearchResult is the JSON response from the test-search endpoint.
Expand Down Expand Up @@ -371,7 +371,7 @@ func (h *TorznabHandler) HandleTestSearch(w http.ResponseWriter, r *http.Request

func writeJSON(w http.ResponseWriter, v interface{}) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(v)
_ = json.NewEncoder(w).Encode(v)
}

func since(start time.Time) string {
Expand Down
2 changes: 1 addition & 1 deletion internal/core/health/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func (c *Checker) checkOne(ctx context.Context, svc db.Service) {
return
}
defer func() {
io.Copy(io.Discard, resp.Body)
_, _ = io.Copy(io.Discard, resp.Body)
resp.Body.Close()
}()

Expand Down
7 changes: 0 additions & 7 deletions internal/core/indexer/prowlarr.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,6 @@ func (pc *ProwlarrCatalog) Refresh(ctx context.Context) error {

pc.logger.Info("prowlarr: found definition files", "count", len(files))

// Step 2: Fetch and parse each YAML file.
// Use a semaphore to limit concurrent requests.
type result struct {
entry CatalogEntry
ok bool
}

// Fetch all definitions via the zipball to avoid per-file rate limits.
pc.logger.Info("prowlarr: downloading zipball...")
entries, errCount, err := pc.fetchAllViaZip(ctx, files)
Expand Down
8 changes: 2 additions & 6 deletions internal/core/indexer/tester.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,7 @@ func TestIndexer(ctx context.Context, kind, url, apiKey string) TestResult {

func testTorznab(ctx context.Context, client *http.Client, baseURL, apiKey string, start time.Time) TestResult {
// Torznab/Newznab caps endpoint: /api?t=caps&apikey=...
capsURL := baseURL
if capsURL != "" && capsURL[len(capsURL)-1] != '/' {
capsURL += "/"
}
capsURL = baseURL + "?t=caps"
capsURL := baseURL + "?t=caps"
if apiKey != "" {
capsURL += "&apikey=" + apiKey
}
Expand Down Expand Up @@ -105,7 +101,7 @@ func testGenericHTTP(ctx context.Context, client *http.Client, url, apiKey strin
return TestResult{Success: false, Message: fmt.Sprintf("Connection failed: %v", err), Duration: since(start)}
}
defer func() {
io.Copy(io.Discard, resp.Body)
_, _ = io.Copy(io.Discard, resp.Body)
resp.Body.Close()
}()

Expand Down
14 changes: 9 additions & 5 deletions internal/events/bus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,21 @@ func TestBusPublishSubscribe(t *testing.T) {

func TestBusPublishSetsTimestamp(t *testing.T) {
bus := New(slog.Default())
var received Event
received := make(chan Event, 1)

bus.Subscribe(func(_ context.Context, e Event) {
received = e
received <- e
})

bus.Publish(context.Background(), Event{Type: TypeConfigUpdated})
time.Sleep(50 * time.Millisecond)

if received.Timestamp.IsZero() {
t.Error("expected non-zero timestamp")
select {
case e := <-received:
if e.Timestamp.IsZero() {
t.Error("expected non-zero timestamp")
}
case <-time.After(1 * time.Second):
t.Fatal("timed out waiting for event")
}
}

Expand Down
36 changes: 24 additions & 12 deletions internal/torznab/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ type Enclosure struct {
// MarshalXML produces the Torznab-compatible XML for an Item.
func (item Item) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
start.Name = xml.Name{Local: "item"}
e.EncodeToken(start)
if err := e.EncodeToken(start); err != nil {
return err
}

writeElement(e, "title", item.Title)
writeElement(e, "guid", item.GUID)
Expand All @@ -103,39 +105,49 @@ func (item Item) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
if encType == "" {
encType = "application/x-bittorrent"
}
e.EncodeToken(xml.StartElement{
if err := e.EncodeToken(xml.StartElement{
Name: xml.Name{Local: "enclosure"},
Attr: []xml.Attr{
{Name: xml.Name{Local: "url"}, Value: item.Enclosure.URL},
{Name: xml.Name{Local: "length"}, Value: strconv.FormatInt(item.Enclosure.Length, 10)},
{Name: xml.Name{Local: "type"}, Value: encType},
},
})
e.EncodeToken(xml.EndElement{Name: xml.Name{Local: "enclosure"}})
}); err != nil {
return err
}
if err := e.EncodeToken(xml.EndElement{Name: xml.Name{Local: "enclosure"}}); err != nil {
return err
}
}

// Torznab attributes
torznabNS := "http://torznab.com/schemas/2015/feed"
for name, value := range item.Attrs {
e.EncodeToken(xml.StartElement{
if err := e.EncodeToken(xml.StartElement{
Name: xml.Name{Space: torznabNS, Local: "attr"},
Attr: []xml.Attr{
{Name: xml.Name{Local: "name"}, Value: name},
{Name: xml.Name{Local: "value"}, Value: value},
},
})
e.EncodeToken(xml.EndElement{Name: xml.Name{Space: torznabNS, Local: "attr"}})
}); err != nil {
return err
}
if err := e.EncodeToken(xml.EndElement{Name: xml.Name{Space: torznabNS, Local: "attr"}}); err != nil {
return err
}
}

e.EncodeToken(xml.EndElement{Name: xml.Name{Local: "item"}})
return nil
return e.EncodeToken(xml.EndElement{Name: xml.Name{Local: "item"}})
}

func writeElement(e *xml.Encoder, name, value string) {
start := xml.StartElement{Name: xml.Name{Local: name}}
e.EncodeToken(start)
e.EncodeToken(xml.CharData(value))
e.EncodeToken(xml.EndElement{Name: xml.Name{Local: name}})
// The outer MarshalXML returns any encoder error via its final
// EncodeToken call, so these helpers ignore errors by design —
// a broken encoder will surface at the next checked call.
_ = e.EncodeToken(start)
_ = e.EncodeToken(xml.CharData(value))
_ = e.EncodeToken(xml.EndElement{Name: xml.Name{Local: name}})
}

// ── Builders ────────────────────────────────────────────────────────────────
Expand Down
2 changes: 1 addition & 1 deletion pkg/sdk/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func setupTestServer(t *testing.T) *httptest.Server {

// Clean all tables for test isolation.
for _, table := range []string{"indexer_tags", "service_tags", "tags", "config_subscriptions", "config_entries", "indexer_assignments", "indexers", "service_capabilities", "services", "filter_presets", "download_clients"} {
sqlDB.Exec("DELETE FROM " + table)
_, _ = sqlDB.Exec("DELETE FROM " + table)
}

logger := slog.Default()
Expand Down
Loading